From fa0e85983c6d713d77bfaa2fb45bec015e5caf05 Mon Sep 17 00:00:00 2001 From: thinkphp Date: Fri, 3 Jun 2016 17:33:52 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=B9=E8=BF=9BModel=E7=B1=BB=E7=9A=84?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=99=A8=E6=9C=BA=E5=88=B6=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20setAttr=E5=92=8C=20getAttr=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/think/Model.php | 354 +++++++++++++++++-------------- library/think/model/Merge.php | 15 +- library/think/model/Relation.php | 10 +- 3 files changed, 203 insertions(+), 176 deletions(-) diff --git a/library/think/Model.php b/library/think/Model.php index 79eb1be1..2ef689fa 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -111,6 +111,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $this->name = basename(str_replace('\\', '/', $this->class)); } + if (empty($this->fieldType)) { + // 获取字段类型信息并缓存 + $this->fieldType = $this->db()->getTableInfo('', 'type'); + } + if (is_null($this->autoWriteTimestamp)) { $this->autoWriteTimestamp = $this->db()->getConfig('auto_timestamp'); } @@ -122,7 +127,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess /** * 获取关联模型实例 * @access protected - * @return \think\model\Relation + * @return Relation */ protected function relation() { @@ -155,7 +160,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess {} /** - * 设置数据对象值 + * 批量设置数据对象值 * @access public * @param mixed $data 数据 * @return $this @@ -171,6 +176,178 @@ abstract class Model implements \JsonSerializable, \ArrayAccess return $this; } + /** + * 修改器 设置数据对象值 + * @access public + * @param string $name 属性名 + * @param mixed $value 属性值 + * @param array $data 数据 + * @return $this + */ + public function setAttr($name, $value, $data = []) + { + if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime, $this->deleteTime])) { + // 自动写入的时间戳字段 + if (isset($this->type[$name])) { + $type = $this->type[$name]; + if (strpos($type, ':')) { + list($type, $param) = explode(':', $type, 2); + } + switch ($type) { + case 'timestamp': + $format = !empty($param) ? $param : $this->dateFormat; + $value = date($format, $_SERVER['REQUEST_TIME']); + break; + case 'datetime': + $value = $_SERVER['REQUEST_TIME']; + break; + } + } elseif (isset($this->fieldType[$name]) && preg_match('/(datetime|timestamp)/is', $this->fieldType[$name])) { + $value = date($this->dateFormat, $_SERVER['REQUEST_TIME']); + } else { + $value = $_SERVER['REQUEST_TIME']; + } + } else { + // 检测修改器 + $method = 'set' . Loader::parseName($name, 1) . 'Attr'; + if (method_exists($this, $method)) { + $value = $this->$method($value, array_merge($data, $this->data)); + } elseif (isset($this->type[$name])) { + // 类型转换 + $value = $this->writeTransform($value, $this->type[$name]); + } + } + + // 标记字段更改 + if (!isset($this->data[$name]) || ($this->data[$name] != $value && !in_array($name, $this->change))) { + $this->change[] = $name; + } + // 设置数据对象属性 + $this->data[$name] = $value; + return $this; + } + + /** + * 数据写入 类型转换 + * @access public + * @param mixed $value 值 + * @param string $type 要转换的类型 + * @return mixed + */ + protected function writeTransform($value, $type) + { + if (strpos($type, ':')) { + list($type, $param) = explode(':', $type, 2); + } + switch ($type) { + case 'integer': + $value = (int) $value; + break; + case 'float': + if (empty($param)) { + $value = (float) $value; + } else { + $value = (float) number_format($value, $param); + } + break; + case 'boolean': + $value = (bool) $value; + break; + case 'datetime': + if (!is_numeric($value)) { + $value = strtotime($value); + } + break; + case 'timestamp': + $format = !empty($param) ? $param : $this->dateFormat; + $value = date($format, is_numeric($value) ? $value : strtotime($value)); + break; + case 'object': + if (is_object($value)) { + $value = json_encode($value, JSON_FORCE_OBJECT); + } + break; + case 'json': + case 'array': + if (is_array($value)) { + $value = json_encode($value, JSON_UNESCAPED_UNICODE); + } + break; + } + return $value; + } + + /** + * 获取器 获取数据对象的值 + * @access public + * @param string $name 名称 + * @return mixed + */ + public function getAttr($name) + { + $value = isset($this->data[$name]) ? $this->data[$name] : null; + + // 检测属性获取器 + $method = 'get' . Loader::parseName($name, 1) . 'Attr'; + if (method_exists($this, $method)) { + return $this->$method($value, $this->data); + } elseif (!is_null($value) && isset($this->type[$name])) { + // 类型转换 + $value = $this->readTransform($value, $this->type[$name]); + } elseif (is_null($value) && method_exists($this, $name)) { + // 获取关联数据 + $value = $this->relation()->getRelation($name); + // 保存关联对象值 + $this->data[$name] = $value; + } + return $value; + } + + /** + * 数据读取 类型转换 + * @access public + * @param mixed $value 值 + * @param string $type 要转换的类型 + * @return mixed + */ + protected function readTransform($value, $type) + { + if (strpos($type, ':')) { + list($type, $param) = explode(':', $type, 2); + } + switch ($type) { + case 'integer': + $value = (int) $value; + break; + case 'float': + if (empty($param)) { + $value = (float) $value; + } else { + $value = (float) number_format($value, $param); + } + break; + case 'boolean': + $value = (bool) $value; + break; + case 'datetime': + $format = !empty($param) ? $param : $this->dateFormat; + $value = date($format, $value); + break; + case 'timestamp': + $format = !empty($param) ? $param : $this->dateFormat; + $value = date($format, strtotime($value)); + break; + case 'json': + case 'array': + $value = json_decode($value, true); + break; + case 'object': + $value = json_decode($value); + break; + } + return $value; + } + /** * 获取对象原始数据 * @access public @@ -216,7 +393,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $item = []; if (!empty($this->append)) { foreach ($this->append as $name) { - $item[$name] = $this->__get($name); + $item[$name] = $this->getAttr($name); } } foreach ($this->data as $key => $val) { @@ -237,7 +414,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $item[$key] = $data; } else { // 模型属性 - $item[$key] = $this->__get($key); + $item[$key] = $this->getAttr($key); } } return !empty($item) ? $item : []; @@ -305,7 +482,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess } // 数据对象赋值 foreach ($data as $key => $value) { - $this->__set($key, $value); + $this->setAttr($key, $value); } if (!empty($where)) { $this->isUpdate = true; @@ -326,7 +503,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 自动写入更新时间 if ($this->autoWriteTimestamp && $this->updateTime) { - $this->__set($this->updateTime, null); + $this->setAttr($this->updateTime, null); } // 事件回调 @@ -372,7 +549,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 自动写入创建时间 if ($this->autoWriteTimestamp && $this->createTime) { - $this->__set($this->createTime, null); + $this->setAttr($this->createTime, null); } if (false === $this->trigger('before_insert', $this)) { @@ -460,7 +637,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $value = null; } if (!in_array($field, $this->change)) { - $this->__set($field, isset($this->data[$field]) ? $this->data[$field] : $value); + $this->setAttr($field, isset($this->data[$field]) ? $this->data[$field] : $value); } } } @@ -1006,98 +1183,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public function __set($name, $value) { - if (empty($this->fieldType)) { - // 获取字段类型信息并缓存 - $this->fieldType = $this->db()->getTableInfo('', 'type'); - } - if (is_null($value) && $this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime, $this->deleteTime])) { - // 自动写入的时间戳字段 - if (isset($this->type[$name])) { - $type = $this->type[$name]; - if (strpos($type, ':')) { - list($type, $param) = explode(':', $type, 2); - } - switch ($type) { - case 'timestamp': - $format = !empty($param) ? $param : $this->dateFormat; - $value = date($format, $_SERVER['REQUEST_TIME']); - break; - case 'datetime': - $value = $_SERVER['REQUEST_TIME']; - break; - } - } elseif (isset($this->fieldType[$name]) && preg_match('/(datetime|timestamp)/is', $this->fieldType[$name])) { - $value = date($this->dateFormat, $_SERVER['REQUEST_TIME']); - } else { - $value = $_SERVER['REQUEST_TIME']; - } - } else { - // 检测修改器 - $method = 'set' . Loader::parseName($name, 1) . 'Attr'; - if (method_exists($this, $method)) { - $value = $this->$method($value, $this->data); - } elseif (isset($this->type[$name])) { - // 类型转换 - $value = $this->writeTransform($value, $this->type[$name]); - } - } - - // 标记字段更改 - if (!isset($this->data[$name]) || ($this->data[$name] != $value && !in_array($name, $this->change))) { - $this->change[] = $name; - } - // 设置数据对象属性 - $this->data[$name] = $value; - } - - /** - * 数据写入 类型转换 - * @access public - * @param mixed $value 值 - * @param string $type 要转换的类型 - * @return mixed - */ - protected function writeTransform($value, $type) - { - if (strpos($type, ':')) { - list($type, $param) = explode(':', $type, 2); - } - switch ($type) { - case 'integer': - $value = (int) $value; - break; - case 'float': - if (empty($param)) { - $value = (float) $value; - } else { - $value = (float) number_format($value, $param); - } - break; - case 'boolean': - $value = (bool) $value; - break; - case 'datetime': - if (!is_numeric($value)) { - $value = strtotime($value); - } - break; - case 'timestamp': - $format = !empty($param) ? $param : $this->dateFormat; - $value = date($format, is_numeric($value) ? $value : strtotime($value)); - break; - case 'object': - if (is_object($value)) { - $value = json_encode($value, JSON_FORCE_OBJECT); - } - break; - case 'json': - case 'array': - if (is_array($value)) { - $value = json_encode($value, JSON_UNESCAPED_UNICODE); - } - break; - } - return $value; + $this->setAttr($name, $value); } /** @@ -1108,67 +1194,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public function __get($name) { - $value = isset($this->data[$name]) ? $this->data[$name] : null; - - // 检测属性获取器 - $method = 'get' . Loader::parseName($name, 1) . 'Attr'; - if (method_exists($this, $method)) { - return $this->$method($value, $this->data); - } elseif (!is_null($value) && isset($this->type[$name])) { - // 类型转换 - $value = $this->readTransform($value, $this->type[$name]); - } elseif (is_null($value) && method_exists($this, $name)) { - // 获取关联数据 - $value = $this->relation()->getRelation($name); - // 保存关联对象值 - $this->data[$name] = $value; - } - return $value; - } - - /** - * 数据读取 类型转换 - * @access public - * @param mixed $value 值 - * @param string $type 要转换的类型 - * @return mixed - */ - protected function readTransform($value, $type) - { - if (strpos($type, ':')) { - list($type, $param) = explode(':', $type, 2); - } - switch ($type) { - case 'integer': - $value = (int) $value; - break; - case 'float': - if (empty($param)) { - $value = (float) $value; - } else { - $value = (float) number_format($value, $param); - } - break; - case 'boolean': - $value = (bool) $value; - break; - case 'datetime': - $format = !empty($param) ? $param : $this->dateFormat; - $value = date($format, $value); - break; - case 'timestamp': - $format = !empty($param) ? $param : $this->dateFormat; - $value = date($format, strtotime($value)); - break; - case 'json': - case 'array': - $value = json_decode($value, true); - break; - case 'object': - $value = json_decode($value); - break; - } - return $value; + return $this->getAttr($name); } /** @@ -1181,7 +1207,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess { if (array_key_exists($name, $this->data)) { return true; - } elseif ($this->__get($name)) { + } elseif ($this->getAttr($name)) { return true; } else { return false; @@ -1213,7 +1239,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // ArrayAccess public function offsetSet($name, $value) { - $this->__set($name, $value); + $this->setAttr($name, $value); } public function offsetExists($name) @@ -1228,7 +1254,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess public function offsetGet($name) { - return $this->__get($name); + return $this->getAttr($name); } /** diff --git a/library/think/model/Merge.php b/library/think/model/Merge.php index f34d8d3a..b26c8494 100644 --- a/library/think/model/Merge.php +++ b/library/think/model/Merge.php @@ -150,24 +150,25 @@ class Merge extends Model public function save($data = [], $where = [], $getId = true) { if (!empty($data)) { + // 数据自动验证 + if (!$this->validateData()) { + return false; + } // 数据对象赋值 foreach ($data as $key => $value) { - $this->__set($key, $value); + $this->setAttr($key, $value); } if (!empty($where)) { $this->isUpdate = true; } } - // 数据自动验证 - if (!$this->validateData()) { - return false; - } + // 数据自动完成 $this->autoCompleteData($this->auto); // 自动写入更新时间 if ($this->autoWriteTimestamp && $this->updateTime) { - $this->__set($this->updateTime, null); + $this->setAttr($this->updateTime, null); } $db = $this->db(); @@ -203,7 +204,7 @@ class Merge extends Model // 自动写入创建时间 if ($this->autoWriteTimestamp && $this->createTime) { - $this->__set($this->createTime, null); + $this->setAttr($this->createTime, null); } if (false === $this->trigger('before_insert', $this)) { diff --git a/library/think/model/Relation.php b/library/think/model/Relation.php index 03e2a04d..c32fe733 100644 --- a/library/think/model/Relation.php +++ b/library/think/model/Relation.php @@ -177,7 +177,7 @@ class Relation if (!isset($data[$result->$localKey])) { $data[$result->$localKey] = []; } - $result->__set($relation, $this->resultSetBuild($data[$result->$localKey], $class)); + $result->setAttr($relation, $this->resultSetBuild($data[$result->$localKey], $class)); } } break; @@ -206,7 +206,7 @@ class Relation $data[$result->$pk] = []; } - $result->__set($relation, $this->resultSetBuild($data[$result->$pk], $class)); + $result->setAttr($relation, $this->resultSetBuild($data[$result->$pk], $class)); } } break; @@ -266,7 +266,7 @@ class Relation if (!isset($data[$result->$localKey])) { $data[$result->$localKey] = []; } - $result->__set($relation, $this->resultSetBuild($data[$result->$localKey], $class)); + $result->setAttr($relation, $this->resultSetBuild($data[$result->$localKey], $class)); } break; case self::BELONGS_TO_MANY: @@ -280,7 +280,7 @@ class Relation if (!isset($data[$pk])) { $data[$pk] = []; } - $result->__set($relation, $this->resultSetBuild($data[$pk], $class)); + $result->setAttr($relation, $this->resultSetBuild($data[$pk], $class)); } break; @@ -315,7 +315,7 @@ class Relation // 设置关联模型属性 $list[$modelName] = []; } - $result->__set($relation, new $model($list[$modelName])); + $result->setAttr($relation, new $model($list[$modelName])); } /**