| <?php |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| namespace think\model; |
|
|
| use think\Db; |
| use think\db\Query; |
| use think\Model; |
|
|
| class Merge extends Model |
| { |
|
|
| protected $relationModel = []; |
| protected $fk = ''; |
| protected $mapFields = []; |
|
|
| |
| |
| |
| |
| |
| public function __construct($data = []) |
| { |
| parent::__construct($data); |
|
|
| |
| if (empty($this->fk)) { |
| $this->fk = strtolower($this->name) . '_id'; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public static function get($data = null, $with = [], $cache = false) |
| { |
| $query = self::parseQuery($data, $with, $cache); |
| $query = self::attachQuery($query); |
| return $query->find($data); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| protected static function attachQuery($query) |
| { |
| $class = new static(); |
| $master = $class->name; |
| $fields = self::getModelField($query, $master, '', $class->mapFields, $class->field); |
| $query->alias($master)->field($fields); |
|
|
| foreach ($class->relationModel as $key => $model) { |
| $name = is_int($key) ? $model : $key; |
| $table = is_int($key) ? $query->getTable($name) : $model; |
| $query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk()); |
| $fields = self::getModelField($query, $name, $table, $class->mapFields, $class->field); |
| $query->field($fields); |
| } |
| return $query; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| protected static function getModelField($query, $name, $table = '', $map = [], $fields = []) |
| { |
| |
| $fields = $fields ?: $query->getTableInfo($table, 'fields'); |
| $array = []; |
| foreach ($fields as $field) { |
| if ($key = array_search($name . '.' . $field, $map)) { |
| |
| $array[] = $name . '.' . $field . ' AS ' . $key; |
| } else { |
| $array[] = $field; |
| } |
| } |
| return $array; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| public static function all($data = null, $with = [], $cache = false) |
| { |
| $query = self::parseQuery($data, $with, $cache); |
| $query = self::attachQuery($query); |
| return $query->select($data); |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| protected function parseData($model, $data) |
| { |
| $item = []; |
| foreach ($data as $key => $val) { |
| if ($this->fk != $key && array_key_exists($key, $this->mapFields)) { |
| list($name, $key) = explode('.', $this->mapFields[$key]); |
| if ($model == $name) { |
| $item[$key] = $val; |
| } |
| } else { |
| $item[$key] = $val; |
| } |
| } |
| return $item; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public function save($data = [], $where = [], $sequence = null) |
| { |
| if (!empty($data)) { |
| |
| if (!$this->validateData($data)) { |
| return false; |
| } |
| |
| foreach ($data as $key => $value) { |
| $this->setAttr($key, $value, $data); |
| } |
| if (!empty($where)) { |
| $this->isUpdate = true; |
| } |
| } |
|
|
| |
| $this->autoCompleteData($this->auto); |
|
|
| |
| if ($this->autoWriteTimestamp && $this->updateTime && !isset($this->data[$this->updateTime])) { |
| $this->setAttr($this->updateTime, null); |
| } |
|
|
| |
| if (false === $this->trigger('before_write', $this)) { |
| return false; |
| } |
|
|
| $db = $this->db(); |
| $db->startTrans(); |
| $pk = $this->getPk(); |
| try { |
| if ($this->isUpdate) { |
| |
| $this->autoCompleteData($this->update); |
|
|
| if (false === $this->trigger('before_update', $this)) { |
| return false; |
| } |
|
|
| if (empty($where) && !empty($this->updateWhere)) { |
| $where = $this->updateWhere; |
| } |
|
|
| |
| $data = $this->getChangedData(); |
| |
| foreach ($this->data as $key => $val) { |
| if ($this->isPk($key)) { |
| $data[$key] = $val; |
| } |
| } |
| |
| $data = $this->parseData($this->name, $data); |
| if (is_string($pk) && isset($data[$pk])) { |
| if (!isset($where[$pk])) { |
| unset($where); |
| $where[$pk] = $data[$pk]; |
| } |
| unset($data[$pk]); |
| } |
| |
| $result = $db->strict(false)->where($where)->update($data); |
|
|
| |
| foreach ($this->relationModel as $key => $model) { |
| $name = is_int($key) ? $model : $key; |
| $table = is_int($key) ? $db->getTable($model) : $model; |
| |
| $data = $this->parseData($name, $data); |
| if (Db::table($table)->strict(false)->where($this->fk, $this->data[$this->getPk()])->update($data)) { |
| $result = 1; |
| } |
| } |
|
|
| |
| $this->trigger('after_update', $this); |
| } else { |
| |
| $this->autoCompleteData($this->insert); |
|
|
| |
| if ($this->autoWriteTimestamp && $this->createTime && !isset($this->data[$this->createTime])) { |
| $this->setAttr($this->createTime, null); |
| } |
|
|
| if (false === $this->trigger('before_insert', $this)) { |
| return false; |
| } |
|
|
| |
| $data = $this->parseData($this->name, $this->data); |
| |
| $result = $db->name($this->name)->strict(false)->insert($data); |
| if ($result) { |
| $insertId = $db->getLastInsID($sequence); |
| |
| if ($insertId) { |
| if (is_string($pk)) { |
| $this->data[$pk] = $insertId; |
| } |
| $this->data[$this->fk] = $insertId; |
| } |
|
|
| |
| $source = $this->data; |
| if ($insertId && is_string($pk) && isset($source[$pk]) && $this->fk != $pk) { |
| unset($source[$pk]); |
| } |
| foreach ($this->relationModel as $key => $model) { |
| $name = is_int($key) ? $model : $key; |
| $table = is_int($key) ? $db->getTable($model) : $model; |
| |
| $data = $this->parseData($name, $source); |
| Db::table($table)->strict(false)->insert($data); |
| } |
| } |
| |
| $this->isUpdate = true; |
| |
| $this->trigger('after_insert', $this); |
| } |
| $db->commit(); |
| |
| $this->trigger('after_write', $this); |
|
|
| $this->origin = $this->data; |
| return $result; |
| } catch (\Exception $e) { |
| $db->rollback(); |
| throw $e; |
| } |
| } |
|
|
| |
| |
| |
| |
| |
| |
| public function delete() |
| { |
| if (false === $this->trigger('before_delete', $this)) { |
| return false; |
| } |
|
|
| $db = $this->db(); |
| $db->startTrans(); |
| try { |
| $result = $db->delete($this->data); |
| if ($result) { |
| |
| $pk = $this->data[$this->getPk()]; |
|
|
| |
| foreach ($this->relationModel as $key => $model) { |
| $table = is_int($key) ? $db->getTable($model) : $model; |
| $query = new Query; |
| $query->table($table)->where($this->fk, $pk)->delete(); |
| } |
| } |
| $this->trigger('after_delete', $this); |
| $db->commit(); |
| return $result; |
| } catch (\Exception $e) { |
| $db->rollback(); |
| throw $e; |
| } |
| } |
|
|
| } |
|
|