diff --git a/library/think/Model.php b/library/think/Model.php index 94b99b94..739f95b5 100644 --- a/library/think/Model.php +++ b/library/think/Model.php @@ -248,8 +248,7 @@ class Model } // 数据自动验证 - $this->dataValidate($data); - if (!empty($this->error)) { + if (!$this->dataValidate($data)) { return false; } @@ -963,8 +962,7 @@ class Model } // 数据自动验证 - $this->dataValidate($data); - if (!empty($this->error)) { + if (!$this->dataValidate($data)) { return false; } @@ -993,104 +991,11 @@ class Model // 验证前清空error $this->error = ''; if (!empty($this->options['validate'])) { - // 获取自动验证规则 - list($rules, $options, $scene) = $this->getDataRule($this->options['validate'], 'validate'); - - if (!isset($options['value_validate'])) { - $options['value_validate'] = []; - } elseif (is_string($options['value_validate'])) { - $options['value_validate'] = explode(',', $options['value_validate']); - } - if (!isset($options['exists_validate'])) { - $options['exists_validate'] = []; - } elseif (is_string($options['exists_validate'])) { - $options['exists_validate'] = explode(',', $options['exists_validate']); - } - foreach ($rules as $key => $rule) { - if (is_numeric($key) && is_array($rule)) { - $key = array_shift($rule); - } - if ((!empty($scene) && !in_array($key, $scene)) || isset($this->error[$key])) { - // 不在指定的场景中或者已经验证过相同的字段 - continue; - } - if (!$this->fieldValidate($key, $rule, $data, $options)) { - break; - } - } - $this->options['validate'] = null; - } - return; - } - - /** - * 字段验证 - * @access protected - * @param string $name 字段名 - * @param mixed $rule 规则 - * @param array $data 数据 - * @param array $options 配置参数 - * @param string $key 子字段名 - * @param array $value 子字段值 - * @return boolean - */ - protected function fieldValidate($name, $rule, &$data, $options = [], $key = null, $value = null) - { - if (is_null($key)) { - $key = $name; - } - // 字段名带有通配符* 需要进行多项验证 - if (false !== $_key = strstr($key, '.*', true)) { - if (is_null($value)) { - $value = $this->getDataValue($data, $_key); - } - if (is_array($value)) { - $key = substr($key, strlen($_key . '.*')); - foreach ($value as $i => $val) { - // 对数组中每一项进行验证 - if (!$this->fieldValidate($name, $rule, $data, $options, $_key . '.' . $i . $key, $val)) { - return false; - } - } - } else { + if (!Validate::check($data, $this->options['validate'])) { + $this->error = Validate::getError(); return false; } - } else { - // 取得对应的键值 - $value = $this->getDataValue($data, $key); - if ((in_array($name, $options['value_validate']) && '' == $value) - || (in_array($name, $options['exists_validate']) && is_null($value))) { - // 不满足自动验证条件 - return true; - } - if ($rule instanceof \Closure) { - // 匿名函数验证 支持传入当前字段和所有字段两个数据 - $result = call_user_func_array($rule, [$value, &$data]); - } elseif (is_string($rule)) { - // 行为验证 用于一次性批量验证 - $result = Hook::exec($rule, '', $data); - } else { - // 验证字段规则 - $result = $this->checkValidate($value, $rule, $data); - } - if (true !== $result) { - // 没有返回true 则表示验证失败 - if (!empty($options['patch'])) { - // 批量验证 - if (is_array($result)) { - if (empty($this->error)) { - $this->error = $result; - } else { - $this->error[] = array_merge($this->error, $result); - } - } else { - $this->error[$key] = $result; - } - } else { - $this->error = $result; - return false; - } - } + $this->options['validate'] = null; } return true; } @@ -1104,274 +1009,11 @@ class Model protected function dataFill(&$data) { if (!empty($this->options['auto'])) { - // 获取自动完成规则 - list($rules, $options, $scene) = $this->getDataRule($this->options['auto'], 'auto'); - - if (!isset($options['value_fill'])) { - $options['value_fill'] = []; - } elseif (is_string($options['value_fill'])) { - $options['value_fill'] = explode(',', $options['value_fill']); - } - if (!isset($options['exists_fill'])) { - $options['exists_fill'] = []; - } elseif (is_string($options['exists_fill'])) { - $options['exists_fill'] = explode(',', $options['exists_fill']); - } - foreach ($rules as $key => $rule) { - if (is_numeric($key) && is_array($rule)) { - $key = array_shift($rule); - } - if (!empty($scene) && !in_array($key, $scene)) { - continue; - } - // 数据自动填充 - $this->autoOperation($key, $rule, $data, $options); - } + Validate::fill($data, $this->options['auto']); $this->options['auto'] = null; } } - /** - * 获取数据值 - * @access protected - * @param array $data 数据 - * @param string|string $key 数据标识 支持数组 - * @return mixed - */ - protected function getDataValue($data, $key) - { - if (is_string($key)) { - if (!strpos($key, '.')) { - return isset($data[$key]) ? $data[$key] : null; - } else { - $key = explode('.', $key); - } - } - foreach ($key as $val) { - if (isset($data[$val])) { - $data = $data[$val]; - } else { - $data = null; - break; - } - } - return $data; - } - - /** - * 获取数据自动验证或者完成的规则定义 - * @access protected - * @param mixed $rules 数据规则 - * @param string $type 数据类型 支持 validate auto - * @return array - */ - protected function getDataRule($rules, $type) - { - if (!is_array($rules)) { - // 读取配置文件中的数据类型定义 - $config = Config::get($type); - if ('validate' == $type && isset($config['__pattern__'])) { - // 全局字段规则 - $this->rule = $config['__pattern__']; - } - if (true === $rules) { - $name = strtolower($this->name); - } elseif (strpos($rules, '.')) { - list($name, $group) = explode('.', $rules); - } else { - $name = $rules; - } - $rules = isset($config[$name]) ? $config[$name] : []; - if (isset($config['__all__'])) { - $rules = array_merge($config['__all__'], $rules); - } - } - if (isset($rules['__option__'])) { - // 参数设置 - $options = $rules['__option__']; - unset($rules['__option__']); - } else { - $options = []; - } - if (isset($group) && isset($options['scene'][$group])) { - // 如果设置了验证适用场景 - $scene = $options['scene'][$group]; - if (is_string($scene)) { - $scene = explode(',', $scene); - } - } else { - $scene = []; - } - return [$rules, $options, $scene]; - } - - /** - * 数据自动填充 - * @access protected - * @param string $name 字段名 - * @param mixed $rule 填充规则 - * @param array $data 数据 - * @param array $options 参数 - * @param string $key 子字段名 - * @param array $value 子字段值 - * @return void - */ - protected function autoOperation($name, $rule, &$data, $options = [], $key = null, $value = null) - { - if (is_null($key)) { - $key = $name; - } - // 字段名带有通配符* 需要进行多项填充 - if (false !== $_key = strstr($key, '.*', true)) { - if (is_null($value)) { - $value = $this->getDataValue($data, $_key); - } - if (is_array($value)) { - $key = substr($key, strlen($_key . '.*')); - foreach ($value as $i => $val) { - // 对数组中每一项进行填充 - $this->autoOperation($name, $rule, $data, $options, $_key . '.' . $i . $key, $val); - } - } - } else { - // 取得对应的键值 - $value = $this->getDataValue($data, $key); - if ((in_array($name, $options['value_fill']) && '' == $value) - || (in_array($name, $options['exists_fill']) && is_null($value))) { - // 不满足自动填充条件 - return; - } - // 匿名函数 用于设置或删除表单中字段的值 - $dataField = function ($key, $val = null) use (&$data) { - $str = '$data'; - foreach (explode('.', $key) as $k) { - $str .= '[\'' . $k . '\']'; - } - if (isset($val)) { - eval($str . "=\$val;"); - } else { - eval('unset(' . $str . ');'); - } - }; - - if ($rule instanceof \Closure) { - $result = call_user_func_array($rule, [$value, &$data]); - } elseif (isset($rule[0]) && $rule[0] instanceof \Closure) { - $result = call_user_func_array($rule[0], [$value, &$data]); - } elseif (!is_array($rule)) { - $result = $rule; - } else { - $val = isset($rule[0]) ? $rule[0] : $rule; - $type = isset($rule[1]) ? $rule[1] : 'value'; - $params = isset($rule[2]) ? (array) $rule[2] : []; - switch ($type) { - case 'behavior': - Hook::exec($val, '', $data); - return; - case 'callback': - array_unshift($params, $value); - $result = call_user_func_array($val, $params); - break; - case 'serialize': - if (empty($val)) { - // 为空则序列化自身 - $serialize = (array) $this->getDataValue($data, $key); - } else { - // 把$data中指定的字段序列化到当前字段 - if (is_string($val)) { - $val = explode(',', $val); - } - $serialize = []; - foreach ($val as $name) { - if (isset($data[$name])) { - $serialize[$name] = $data[$name]; - unset($data[$name]); - } - } - } - $fun = !empty($params['type']) ? $params['type'] : 'serialize'; - $result = $fun($serialize); - break; - case 'ignore': - if ($val === $value) { - // 从$data中移除$key - $dataField($key); - } - return; - case 'value': - default: - $result = $val; - break; - } - } - // 设置$data中$key的值 - $dataField($key, $result); - } - } - - /** - * 验证字段规则 - * @access protected - * @param mixed $value 字段值 - * @param mixed $val 验证规则 - * @param array $data 数据 - * @return string|true - */ - protected function checkValidate($value, $val, &$data) - { - $rule = $val[0]; - $msg = isset($val[1]) ? $val[1] : ''; - $type = isset($val[2]) ? $val[2] : 'regex'; - $options = isset($val[3]) ? (array) $val[3] : []; - if ($rule instanceof \Closure) { - // 匿名函数验证 支持传入当前字段和所有字段两个数据 - $result = call_user_func_array($rule, [$value, &$data]); - } else { - switch ($type) { - case 'callback': - array_unshift($options, $value); - $result = call_user_func_array($rule, $options); - break; - case 'behavior': - // 行为验证 - $result = Hook::exec($rule, '', $data); - break; - case 'filter': // 使用filter_var验证 - $result = false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $options); - break; - case 'confirm': - $result = $this->getDataValue($data, $rule) == $value; - break; - case 'in': - case 'notin': - $range = is_array($rule) ? $rule : explode(',', $rule); - $result = 'in' == $type ? in_array($value, $range) : !in_array($value, $range); - break; - case 'between':// 验证是否在某个范围 - case 'notbetween': // 验证是否不在某个范围 - if (is_string($rule)) { - $rule = explode(',', $rule); - } - list($min, $max) = $rule; - $result = 'between' == $type ? $value >= $min && $value <= $max : $value < $min || $value > $max; - break; - case 'regex': - default: - if (isset($this->rule[$rule])) { - $rule = $this->rule[$rule]; - } - if (!(0 === strpos($rule, '/') && preg_match('/\/[imsU]{0,4}$/', $rule))) { - // 不是正则表达式则两端补上/ - $rule = '/^' . $rule . '$/'; - } - $result = 1 === preg_match($rule, (string) $value); - break; - } - } - // 验证失败返回错误信息 - return (false !== $result) ? $result : $msg; - } - /** * 切换当前的数据库连接 * @access public @@ -1544,7 +1186,7 @@ class Model } $fields = array_keys($info); - $bind = $type = []; + $bind = $type = []; foreach ($info as $key => $val) { // 记录字段类型 $type[$key] = $val['type']; diff --git a/library/think/Validate.php b/library/think/Validate.php new file mode 100644 index 00000000..a789fe2f --- /dev/null +++ b/library/think/Validate.php @@ -0,0 +1,471 @@ + +// +---------------------------------------------------------------------- + +namespace think; + +class Validate +{ + protected static $rule = [ + 'require' => '/\S+/', + 'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/', + 'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(:\d+)?(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/', + 'currency' => '/^\d+(\.\d+)?$/', + 'number' => '/^\d+$/', + 'zip' => '/^\d{6}$/', + 'integer' => '/^[-\+]?\d+$/', + 'double' => '/^[-\+]?\d+(\.\d+)?$/', + 'english' => '/^[A-Za-z]+$/', + ]; + protected static $error = []; + + /** + * 数据自动验证 + * @access protected + * @param array $data 数据 + * @param array $rules 验证规则 + * @param string $config 规则配置名 验证规则不是数组的话读取配置参数 + * @return void + */ + public static function check(&$data, $rules, $config = 'validate') + { + // 获取自动验证规则 + list($rules, $options, $scene) = self::getDataRule($rules, $config); + if (!isset($options['value_validate'])) { + $options['value_validate'] = []; + } elseif (is_string($options['value_validate'])) { + $options['value_validate'] = explode(',', $options['value_validate']); + } + if (!isset($options['exists_validate'])) { + $options['exists_validate'] = []; + } elseif (is_string($options['exists_validate'])) { + $options['exists_validate'] = explode(',', $options['exists_validate']); + } + + foreach ($rules as $key => $val) { + if (is_numeric($key) && is_array($val)) { + $key = array_shift($val); + } + if (!empty($scene) && !in_array($key, $scene)) { + continue; + } + // 获取数据 支持二维数组 + $value = self::getDataValue($data, $key); + + if ((in_array($key, $options['value_validate']) && '' == $value) + || (in_array($key, $options['exists_validate']) && is_null($value))) { + // 不满足自动验证条件 + continue; + } + $result = true; + if ($val instanceof \Closure) { + // 匿名函数验证 支持传入当前字段和所有字段两个数据 + $result = self::callback($value, $val, $data); + } elseif (is_string($val)) { + // 行为验证 用于一次性批量验证 + $result = self::behavior($val, $data); + } else { + // 验证字段规则 + $result = self::checkItem($value, $val, $data); + } + if (true !== $result) { + // 没有返回true 则表示验证失败 + if (!empty($options['patch'])) { + // 批量验证 + if (is_array($result)) { + self::$error[] = $result; + } else { + self::$error[$key] = $result; + } + } else { + self::$error = $result; + return false; + } + } + } + return !empty(self::$error) ? false : true; + } + + // 自动填充 + public static function fill(&$data, $rules, $config = 'auto') + { + // 获取自动完成规则 + list($rules, $options, $scene) = self::getDataRule($rules, $config); + if (!isset($options['value_fill'])) { + $options['value_fill'] = []; + } elseif (is_string($options['value_fill'])) { + $options['value_fill'] = explode(',', $options['value_fill']); + } + if (!isset($options['exists_fill'])) { + $options['exists_fill'] = []; + } elseif (is_string($options['exists_fill'])) { + $options['exists_fill'] = explode(',', $options['exists_fill']); + } + + foreach ($rules as $key => $val) { + if (is_numeric($key) && is_array($val)) { + $key = array_shift($val); + } + if (!empty($scene) && !in_array($key, $scene)) { + continue; + } + // 数据自动填充 + self::fillItem($key, $val, $data, $options); + } + return $data; + } + + /** + * 数据自动填充 + * @access protected + * @param string $key 字段名 + * @param mixed $val 填充规则 + * @param array $data 数据 + * @param array $options 参数 + * @return void + */ + protected static function fillItem($key, $val, &$data, $options = []) + { + // 获取数据 支持二维数组 + $value = self::getDataValue($data, $key); + if (strpos($key, '.')) { + list($name1, $name2) = explode('.', $key); + } + if ((in_array($key, $options['value_fill']) && '' == $value) + || (in_array($key, $options['exists_fill']) && is_null($value))) { + // 不满足自动填充条件 + return; + } + if ($val instanceof \Closure) { + $result = self::callback($value, $val, $data); + } elseif (isset($val[0]) && $val[0] instanceof \Closure) { + $result = self::callback($value, $val[0], $data); + } elseif (!is_array($val)) { + $result = $val; + } else { + $rule = isset($val[0]) ? $val[0] : $val; + $type = isset($val[1]) ? $val[1] : 'value'; + $params = isset($val[2]) ? (array) $val[2] : []; + switch ($type) { + case 'behavior': + self::behavior($rule, $data); + return; + case 'callback': + $result = self::callback($value, $rule, $data, $params); + break; + case 'serialize': + $result = self::serialize($value, $rule, $data, $params); + break; + case 'ignore': + if ($rule === $value) { + if (strpos($key, '.')) { + unset($data[$name1][$name2]); + } else { + unset($data[$key]); + } + } + return; + case 'value': + default: + $result = $rule; + break; + } + } + if (strpos($key, '.')) { + $data[$name1][$name2] = $result; + } else { + $data[$key] = $result; + } + } + + /** + * 验证字段规则 + * @access protected + * @param mixed $value 字段值 + * @param mixed $val 验证规则 + * @param array $data 数据 + * @return string|true + */ + protected static function checkItem($value, $val, &$data) + { + $rule = $val[0]; + $msg = isset($val[1]) ? $val[1] : ''; + $type = isset($val[2]) ? $val[2] : 'regex'; + $options = isset($val[3]) ? (array) $val[3] : []; + if ($rule instanceof \Closure) { + // 匿名函数验证 支持传入当前字段和所有字段两个数据 + $result = self::callback($value, $rule, $data, $options); + } else { + switch ($type) { + case 'callback': + $result = self::callback($value, $rule, $data, $options); + break; + case 'behavior': + // 行为验证 + $result = self::behavior($rule, $data); + break; + case 'filter': // 使用filter_var验证 + $result = self::filter($value, $rule, $options); + break; + case 'confirm': + $result = self::confirm($value, $rule, $data); + break; + case 'in': + $result = self::in($value, $rule); + break; + case 'notin': + $result = self::notin($value, $rule); + break; + case 'between': // 验证是否在某个范围 + $result = self::between($value, $rule); + break; + case 'notbetween': // 验证是否不在某个范围 + $result = self::notbetween($value, $rule); + break; + case 'regex': + default: + $result = self::regex($value, $rule); + break; + } + } + // 验证失败返回错误信息 + return (false !== $result) ? $result : $msg; + } + + /** + * 验证是否和某个字段的值一致 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @param array $data 数据 + * @return bool + */ + public static function confirm($value, $rule, $data) + { + return $value == $data[$rule]; + } + + /** + * 使用callback方式验证或者填充 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @param array $data 数据 + * @param array $params 参数 + * @return mixed + */ + public static function callback($value, $rule, &$data, $params = []) + { + if ($rule instanceof \Closure) { + return call_user_func_array($rule, [$value, &$data]); + } + array_unshift($params, $value); + return call_user_func_array($rule, $params); + } + + /** + * 使用行为类验证或者填充 + * @access public + * @param mixed $rule 验证规则 + * @param array $data 数据 + * @return mixed + */ + public static function behavior($rule, $data) + { + // 行为验证 + return Hook::exec($rule, '', $data); + } + + /** + * 序列化填充 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @param array $data 数据 + * @param array $params 参数 + * @return mixed + */ + public static function serialize($value, $rule, &$data, $params = []) + { + if (is_string($rule)) { + $rule = explode(',', $rule); + } + $serialize = []; + foreach ($rule as $name) { + if (isset($data[$name])) { + $serialize[$name] = $data[$name]; + unset($data[$name]); + } + } + $fun = !empty($params['type']) ? $params['type'] : 'serialize'; + return $fun($serialize); + } + + /** + * 使用filter_var方式验证 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @param array $params 参数 + * @return bool + */ + public static function filter($value, $rule, $params = []) + { + $result = filter_var($value, is_int($rule) ? $rule : filter_id($rule), $params); + return false === $result ? false : true; + } + + /** + * 验证是否在范围内 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @return bool + */ + public static function in($value, $rule) + { + $range = is_array($rule) ? $rule : explode(',', $rule); + return in_array($value, $range); + } + + /** + * 验证是否不在某个范围 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @return bool + */ + public static function notin($value, $rule) + { + $range = is_array($rule) ? $rule : explode(',', $rule); + return !in_array($value, $range); + } + + /** + * between验证数据 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @return mixed + */ + public static function between($value, $rule) + { + if (is_string($rule)) { + $rule = explode(',', $rule); + } + list($min, $max) = $rule; + return $value >= $min && $value <= $max; + } + + /** + * 使用notbetween验证数据 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @return mixed + */ + public static function notbetween($value, $rule) + { + if (is_string($rule)) { + $rule = explode(',', $rule); + } + list($min, $max) = $rule; + return $value < $min || $value > $max; + } + + /** + * 使用正则验证数据 + * @access public + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @return mixed + */ + public static function regex($value, $rule) + { + if (isset(self::$rule[$rule])) { + $rule = self::$rule[$rule]; + } + if (!(0 === strpos($rule, '/') && preg_match('/\/[imsU]{0,4}$/', $rule))) { + // 不是正则表达式则两端补上/ + $rule = '/^' . $rule . '$/'; + } + return 1 === preg_match($rule, (string) $value); + } + + // 获取错误信息 + public static function getError() + { + return self::$error; + } + + /** + * 获取数据值 + * @access protected + * @param array $data 数据 + * @param string $key 数据标识 支持二维 + * @return mixed + */ + protected static function getDataValue($data, $key) + { + if (strpos($key, '.')) { + // 支持二维数组验证 + list($name1, $name2) = explode('.', $key); + $value = isset($data[$name1][$name2]) ? $data[$name1][$name2] : null; + } else { + $value = isset($data[$key]) ? $data[$key] : null; + } + return $value; + } + + /** + * 获取数据自动验证或者完成的规则定义 + * @access protected + * @param mixed $rules 数据规则 + * @param string $config 配置参数 + * @return array + */ + protected static function getDataRule($rules, $config) + { + if (!is_array($rules)) { + // 读取配置文件中的数据类型定义 + $config = Config::get($config); + if (isset($config['__pattern__'])) { + // 全局字段规则 + self::$rule = $config['__pattern__']; + } + if (strpos($rules, '.')) { + list($name, $group) = explode('.', $rules); + } else { + $name = $rules; + } + $rules = $config[$name]; + if (isset($config['__all__'])) { + $rules = array_merge($config['__all__'], $rules); + } + } + if (isset($rules['__option__'])) { + // 参数设置 + $options = $rules['__option__']; + unset($rules['__option__']); + } else { + $options = []; + } + if (isset($group) && isset($options['scene'][$group])) { + // 如果设置了验证适用场景 + $scene = $options['scene'][$group]; + if (is_string($scene)) { + $scene = explode(',', $scene); + } + } else { + $scene = []; + } + return [$rules, $options, $scene]; + } +} diff --git a/tests/thinkphp/library/think/modelTest.php b/tests/thinkphp/library/think/modelTest.php index c54ab2d7..344f7f80 100644 --- a/tests/thinkphp/library/think/modelTest.php +++ b/tests/thinkphp/library/think/modelTest.php @@ -15,6 +15,7 @@ namespace tests\thinkphp\library\think; +use think\Config; use think\Model; class modelTest extends \PHPUnit_Framework_TestCase @@ -36,7 +37,7 @@ class modelTest extends \PHPUnit_Framework_TestCase public function testValidate() { $model = new Model('', $this->getConfig()); - $data = $_POST = [ + $data = $_POST = [ 'username' => 'username', 'nickname' => 'nickname', 'password' => '123456', @@ -59,7 +60,7 @@ class modelTest extends \PHPUnit_Framework_TestCase }, ], 'user' => [ - ['username', [&$this, 'checkName'], '用户名长度为5到15个字符', 'callback', 'username'], + ['username', [ & $this, 'checkName'], '用户名长度为5到15个字符', 'callback', 'username'], ['username', function ($value, $data) { return 'admin' == $value ? '此用户名已被使用' : true; }], @@ -81,7 +82,7 @@ class modelTest extends \PHPUnit_Framework_TestCase ], ], ]; - \think\Config::set('validate', $validate); + Config::set('validate', $validate); $result = $model->validate('user.add')->create(); $this->assertEmpty($model->getError()); @@ -90,46 +91,6 @@ class modelTest extends \PHPUnit_Framework_TestCase $result = $model->validate('user.edit')->create($data); $this->assertEmpty($model->getError()); - // 测试带.和*的键名 - $data = [ - 'code' => '', - 'name' => ['a' => '', 'b' => ''], - 'sku' => [ - 0 => [ - 0 => [ - 'item' => 'item', - 'price' => '', - ], - 1 => [ - 'item' => 'item2', - 'price' => '', - ], - ], - ], - ]; - $test = [ - 'code' => function ($value, $data) { - return empty($value) ? ['code' => 'not empty'] : true; - }, - 'name.*' => ['/.+/', 'not empty'], - 'sku.*.*.price' => ['/\d+/', 'mast int'], - '__option__' => [ - 'patch' => true, - ], - ]; - $result = $model->validate($test)->create($data); - $msg = [ - 'code' => 'not empty', - 'name.a' => 'not empty', - 'name.b' => 'not empty', - 'sku.0.0.price' => 'mast int', - 'sku.0.1.price' => 'mast int', - ]; - $this->assertEquals($msg, $model->getError()); - - unset($test['__option__']['patch']); - $result = $model->field('code')->validate($test)->create($data); - $this->assertEquals(['code' => 'not empty'], $model->getError()); } public function checkName($value, $field) @@ -150,15 +111,14 @@ class modelTest extends \PHPUnit_Framework_TestCase 'username' => '', 'nickname' => 'nickname', 'phone' => ' 123456', - 'hobby' => ['1', '2'], 'cityid' => '1', 'a' => 'a', 'b' => 'b', ]; - $auto = [ + $auto = [ 'user' => [ '__option__' => [ - 'scene' => [ + 'scene' => [ 'edit' => 'username,nickname,phone,hobby,cityid,address,integral,reg_time,login_time,ab', ], 'value_fill' => 'username,phone', @@ -166,11 +126,10 @@ class modelTest extends \PHPUnit_Framework_TestCase ], 'username' => ['strtolower', 'callback'], 'password' => ['md5', 'callback'], - 'nickname' => [[&$this, 'fillName'], 'callback', 'cn_'], + 'nickname' => [[ & $this, 'fillName'], 'callback', 'cn_'], 'phone' => function ($value, $data) { return trim($value); }, - 'hobby' => ['', 'serialize'], 'cityid' => ['1', 'ignore'], 'address' => ['address'], 'integral' => 0, @@ -181,11 +140,10 @@ class modelTest extends \PHPUnit_Framework_TestCase 'ab' => ['a,b', 'serialize'], ], ]; - \think\Config::set('auto', $auto); + Config::set('auto', $auto); $result = $model->auto('user.edit')->create($data); $data['nickname'] = 'cn_nickname'; $data['phone'] = '123456'; - $data['hobby'] = serialize($data['hobby']); $data['address'] = 'address'; $data['integral'] = 0; $data['reg_time'] = time(); @@ -194,31 +152,6 @@ class modelTest extends \PHPUnit_Framework_TestCase unset($data['cityid'], $data['a'], $data['b']); $this->assertEquals($data, $result); - // 测试带.和*的键名 - $data = [ - 'name' => ['a' => 'a', 'b' => 'b'], - 'goods' => [ - 0 => [ - 0 => [ - 'item' => 'item', - 'price' => '', - ], - 1 => [ - 'item' => 'item2', - 'price' => '', - ], - ], - ], - ]; - $test = [ - 'name.*' => 'name', - 'goods.*.*.price' => 100, - ]; - $result = $model->auto($test)->create($data); - $data['name']['a'] = $data['name']['b'] = 'name'; - $data['goods'][0][0]['price'] = 100; - $data['goods'][0][1]['price'] = 100; - $this->assertEquals($data, $result); } public function fillName($value, $prefix) @@ -290,8 +223,8 @@ EOF; 'status' => 1, 'create_time' => $time, ]; - $user_id = $user_model->data($data)->add(); - $data = [ + $user_id = $user_model->data($data)->add(); + $data = [ 'username' => 'test2', 'password' => md5('000000'), 'status' => 1, @@ -299,7 +232,7 @@ EOF; ]; $user_model->add($data, true); - $data = [ + $data = [ [ 'user_id' => $user_id, 'consignee' => '张三', @@ -324,7 +257,7 @@ EOF; $address_model = new Model('user_address', $config); $address_id = $address_model->addAll($data, [], true); - $data = [ + $data = [ [ 'user_id' => $user_id, 'sn' => '10001', @@ -347,7 +280,7 @@ EOF; $address_model = new Model('order', $config); $address_model->addAll($data); - $data = [ + $data = [ 'user_id' => $user_id, 'role_id' => 1, ]; @@ -365,8 +298,8 @@ EOF; $result = $user_model->query($sql); $id = $result[0]['id']; $time = $result[0]['create_time']; - $bind = ['create_time' => $time, 'status' => 1]; - $info = $user_model->where(['create_time'=>':create_time'])->where(['status' => ':status'])->bind($bind)->field(true)->find(['cache' => ['key' => true]]); + $bind = ['create_time' => $time, 'status' => 1]; + $info = $user_model->where(['create_time' => ':create_time'])->where(['status' => ':status'])->bind($bind)->field(true)->find(['cache' => ['key' => true]]); $data = [ 'id' => $id, 'username' => 'test', @@ -377,8 +310,8 @@ EOF; $this->assertEquals($data, $info); $_GET['id'] = $id; - $result = $user_model->where(['id' => ':id'])->bind('id', $_GET['id'])->field('password,create_time', true)->order('id')->limit('0,10')->select(['cache' => ['key' => true, 'expire' => 0], 'index' => 'username']); - $data = [ + $result = $user_model->where(['id' => ':id'])->bind('id', $_GET['id'])->field('password,create_time', true)->order('id')->limit('0,10')->select(['cache' => ['key' => true, 'expire' => 0], 'index' => 'username']); + $data = [ 'id' => $id, 'username' => 'test', 'status' => '1', @@ -386,8 +319,8 @@ EOF; $this->assertEquals($data, $result['test']); $_GET['status'] = '1'; - $result = $user_model->where(['status' => ':status'])->bind('status', $_GET['status'], \PDO::PARAM_INT)->field('password,create_time', true)->order('id', 'desc')->index('id,username')->page('0,10')->select(); - $data = [ + $result = $user_model->where(['status' => ':status'])->bind('status', $_GET['status'], \PDO::PARAM_INT)->field('password,create_time', true)->order('id', 'desc')->index('id,username')->page('0,10')->select(); + $data = [ '1' => 'test', '2' => 'test2', ]; @@ -411,7 +344,7 @@ EOF; ]; $this->assertEquals($data, $result); - $result = $user_model->scope(['field'=>'username', 'where'=>'status=1'])->select(); + $result = $user_model->scope(['field' => 'username', 'where' => 'status=1'])->select(); $data = [ ['username' => 'test'], ['username' => 'test2'], @@ -419,17 +352,16 @@ EOF; $this->assertEquals($data, $result); $result = $user_model->master()->lock(true)->distinct(true)->force('create_time')->comment('查询用户名')->field('username')->fetchSql(true)->select(); - $sql = 'SELECT DISTINCT `username` FROM `tp_user` FORCE INDEX ( create_time ) FOR UPDATE /* 查询用户名 */'; + $sql = 'SELECT DISTINCT `username` FROM `tp_user` FORCE INDEX ( create_time ) FOR UPDATE /* 查询用户名 */'; $this->assertEquals($sql, $result); - $order_model = new Model('order', $this->getConfig()); $result = $order_model->field('user_id,sum(amount) amount')->group('user_id')->having('sum(amount) > 1000')->select(); $this->assertEmpty($result); $result = $order_model->getLastSql(); - $sql = 'SELECT `user_id`,sum(amount) amount FROM `tp_order` GROUP BY user_id HAVING sum(amount) > 1000 '; + $sql = 'SELECT `user_id`,sum(amount) amount FROM `tp_order` GROUP BY user_id HAVING sum(amount) > 1000 '; $this->assertEquals($sql, $result); } @@ -438,7 +370,7 @@ EOF; $config = $this->getConfig(); $user_model = new Model('user', $config); - $join = [ + $join = [ [['order o', 'tp_'], 'u.id=o.user_id'], [['user_address' => 'a'], 'u.id=a.user_id'], ]; @@ -464,11 +396,10 @@ EOF; ]; $this->assertEquals($data, $result[0]); - $order_model = new Model('order', $config); - $subsql = $order_model->limit(1)->buildSql(); - $result = $user_model->alias('u')->join($subsql. ' o', 'u.id=o.user_id', 'left')->field('u.username,o.amount')->select(); - $data = [ + $subsql = $order_model->limit(1)->buildSql(); + $result = $user_model->alias('u')->join($subsql . ' o', 'u.id=o.user_id', 'left')->field('u.username,o.amount')->select(); + $data = [ 'username' => 'test', 'amount' => '200', ]; @@ -505,10 +436,10 @@ EOF; $data = [ 'id' => '1', - 'total' => '180.50', + 'total' => '180.50', 'status' => 1, 'create_time' => time(), - 'about' => '', + 'about' => '', ]; \think\Config::set('db_fields_strict', false); $info = $order_model->where(['id' => 1])->map('amount', 'total')->find(); @@ -525,7 +456,7 @@ EOF; $flag = $order_model->where(['amount' => ['lt', 200]])->setField('freight_fee', 15); $this->assertSame(1, $flag); - $map = [ + $map = [ 'amount' => ['gt', 300], 'freight_fee' => ['gt', 0], ]; @@ -548,7 +479,7 @@ EOF; 'remark' => 'remark', ]; $info = $ru_model->where(['user_id' => 1])->find(); - $flag = $ru_model->data($data)->save(); + $flag = $ru_model->data($data)->save(); $this->assertSame(1, $flag); } @@ -559,8 +490,8 @@ EOF; $model->username = 'test'; $data = [ - 'first' => 'a', - 'last' => 'z', + 'first' => 'a', + 'last' => 'z', 'username' => 'test', ]; $this->assertEquals($data, $model->data()); @@ -608,7 +539,7 @@ EOF; $flag = $ru_model->delete(['1', '1']); $this->assertEquals(1, $flag); - $sql = <<