diff --git a/library/think/Model.php b/library/think/Model.php index 16638648..9ede8043 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -38,7 +38,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess protected $cache = []; // 记录改变字段 protected $change = []; - // 数据表主键 + // 数据表主键 复合主键使用数组定义 protected $pk = 'id'; // 错误信息 protected $error; @@ -57,6 +57,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess 'update_time' => 'time', ]; + // 字段类型或者格式转换 + protected $type = []; // 当前执行的关联类型 private $relation; // 是否为更新 @@ -154,6 +156,26 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $value = $this->$method($value, $this->data); } + // 类型转换 或者 字符串处理 + if (isset($this->type[$name])) { + $type = $this->type[$name]; + switch ($type) { + case 'integer': + $value = (int) $value; + break; + case 'float': + $value = (float) $value; + break; + case 'boolean': + $value = (bool) $value; + break; + default: + if (is_callable($type)) { + $value = call_user_func_array($type, [$value]); + } + } + } + // 设置数据对象属性 if (isset($this->data[$name]) && $this->data[$name] != $value && !in_array($name, $this->change)) { $this->change[] = $name; @@ -172,6 +194,26 @@ abstract class Model implements \JsonSerializable, \ArrayAccess { $value = isset($this->data[$name]) ? $this->data[$name] : null; + // 类型转换 + if (!is_null($value) && isset($this->type[$name])) { + $type = $this->type[$name]; + switch ($type) { + case 'integer': + $value = (int) $value; + break; + case 'float': + $value = (float) $value; + break; + case 'boolean': + $value = (bool) $value; + break; + default: + if (is_callable($type)) { + $value = call_user_func_array($type, [$value]); + } + } + } + // 检测属性获取器 $method = 'get' . Loader::parseName($name, 1) . 'Attr'; if (method_exists($this, $method)) { diff --git a/library/think/db/Driver.php b/library/think/db/Driver.php index 0f6069fb..60c0659a 100644 --- a/library/think/db/Driver.php +++ b/library/think/db/Driver.php @@ -539,13 +539,13 @@ abstract class Driver $info = $this->getFields($tableName); // 字段大小写转换 switch ($this->params[PDO::ATTR_CASE]) { - case \PDO::CASE_LOWER: + case PDO::CASE_LOWER: $info = array_change_key_case($info); break; - case \PDO::CASE_UPPER: + case PDO::CASE_UPPER: $info = array_change_key_case($info, CASE_UPPER); break; - case \PDO::CASE_NATURAL: + case PDO::CASE_NATURAL: default: // 不做转换 } @@ -556,11 +556,11 @@ abstract class Driver // 记录字段类型 $type[$key] = $val['type']; if (preg_match('/(int|double|float|decimal|real|numeric|serial)/is', $val['type'])) { - $bind[$key] = \PDO::PARAM_INT; + $bind[$key] = PDO::PARAM_INT; } elseif (preg_match('/bool/is', $val['type'])) { - $bind[$key] = \PDO::PARAM_BOOL; + $bind[$key] = PDO::PARAM_BOOL; } else { - $bind[$key] = \PDO::PARAM_STR; + $bind[$key] = PDO::PARAM_STR; } if (!empty($val['primary'])) { $pk[] = $key; @@ -1248,7 +1248,7 @@ abstract class Driver foreach ($options['where']['AND'] as $key => $val) { $key = trim($key); if (in_array($key, $fields, true) && is_scalar($val) && empty($this->bind[$key])) { - $this->_parseType($options['where']['AND'], $key, $options['table']); + $this->parseTypeBind($options['where']['AND'], $key, $options['table']); } } } @@ -1256,7 +1256,7 @@ abstract class Driver foreach ($options['where']['OR'] as $key => $val) { $key = trim($key); if (in_array($key, $fields, true) && is_scalar($val) && empty($this->bind[$key])) { - $this->_parseType($options['where']['OR'], $key, $options['table']); + $this->parseTypeBind($options['where']['OR'], $key, $options['table']); } } } @@ -1273,30 +1273,21 @@ abstract class Driver } /** - * 数据类型检测和自动转换 + * 数据字段自动类型绑定 * @access protected * @param array $data 数据 * @param string $key 字段名 * @param string $tableName 表名 * @return void */ - protected function _parseType(&$data, $key, $tableName = '') + protected function parseTypeBind(&$data, $key, $tableName = '') { if (':' == substr($data[$key], 0, 1) && isset($this->bind[substr($data[$key], 1)])) { // 已经绑定 无需再次绑定 请确保bind方法优先执行 return; } - $binds = $this->getTableInfo($tableName, 'bind'); - $type = $this->getTableInfo($tableName, 'type'); - // 强制类型转换 - if (false !== strpos($type[$key], 'int') && false !== strpos($type[$key], 'int')) { - $data[$key] = (int) $data[$key]; - } elseif (false !== strpos($type[$key], 'float') || false !== strpos($type[$key], 'double')) { - $data[$key] = (float) $data[$key]; - } elseif (false !== strpos($type[$key], 'bool')) { - $data[$key] = (bool) $data[$key]; - } - $this->bind[$key] = [$data[$key], isset($binds[$key]) ? $binds[$key] : \PDO::PARAM_STR]; + $binds = $this->getTableInfo($tableName, 'bind'); + $this->bind[$key] = [$data[$key], isset($binds[$key]) ? $binds[$key] : PDO::PARAM_STR]; $data[$key] = ':' . $key; } @@ -1367,7 +1358,7 @@ abstract class Driver $result[$item] = 'NULL'; } elseif (is_scalar($val)) { // 过滤非标量数据 - $this->_parseType($data, $key); + $this->parseTypeBind($data, $key); $result[$item] = $data[$key]; } }