mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-07 07:12:47 +08:00
增加Validate类和测试
This commit is contained in:
@@ -248,8 +248,7 @@ class Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 数据自动验证
|
// 数据自动验证
|
||||||
$this->dataValidate($data);
|
if (!$this->dataValidate($data)) {
|
||||||
if (!empty($this->error)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -963,8 +962,7 @@ class Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 数据自动验证
|
// 数据自动验证
|
||||||
$this->dataValidate($data);
|
if (!$this->dataValidate($data)) {
|
||||||
if (!empty($this->error)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -993,105 +991,12 @@ class Model
|
|||||||
// 验证前清空error
|
// 验证前清空error
|
||||||
$this->error = '';
|
$this->error = '';
|
||||||
if (!empty($this->options['validate'])) {
|
if (!empty($this->options['validate'])) {
|
||||||
// 获取自动验证规则
|
if (!Validate::check($data, $this->options['validate'])) {
|
||||||
list($rules, $options, $scene) = $this->getDataRule($this->options['validate'], 'validate');
|
$this->error = Validate::getError();
|
||||||
|
return false;
|
||||||
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;
|
$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 {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1104,274 +1009,11 @@ class Model
|
|||||||
protected function dataFill(&$data)
|
protected function dataFill(&$data)
|
||||||
{
|
{
|
||||||
if (!empty($this->options['auto'])) {
|
if (!empty($this->options['auto'])) {
|
||||||
// 获取自动完成规则
|
Validate::fill($data, $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);
|
|
||||||
}
|
|
||||||
$this->options['auto'] = null;
|
$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
|
* @access public
|
||||||
|
|||||||
471
library/think/Validate.php
Normal file
471
library/think/Validate.php
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
<?php
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
// | Author: liu21st <liu21st@gmail.com>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
namespace tests\thinkphp\library\think;
|
namespace tests\thinkphp\library\think;
|
||||||
|
|
||||||
|
use think\Config;
|
||||||
use think\Model;
|
use think\Model;
|
||||||
|
|
||||||
class modelTest extends \PHPUnit_Framework_TestCase
|
class modelTest extends \PHPUnit_Framework_TestCase
|
||||||
@@ -59,7 +60,7 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
'user' => [
|
'user' => [
|
||||||
['username', [&$this, 'checkName'], '用户名长度为5到15个字符', 'callback', 'username'],
|
['username', [ & $this, 'checkName'], '用户名长度为5到15个字符', 'callback', 'username'],
|
||||||
['username', function ($value, $data) {
|
['username', function ($value, $data) {
|
||||||
return 'admin' == $value ? '此用户名已被使用' : true;
|
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();
|
$result = $model->validate('user.add')->create();
|
||||||
$this->assertEmpty($model->getError());
|
$this->assertEmpty($model->getError());
|
||||||
|
|
||||||
@@ -90,46 +91,6 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
$result = $model->validate('user.edit')->create($data);
|
$result = $model->validate('user.edit')->create($data);
|
||||||
$this->assertEmpty($model->getError());
|
$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)
|
public function checkName($value, $field)
|
||||||
@@ -150,7 +111,6 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
'username' => '',
|
'username' => '',
|
||||||
'nickname' => 'nickname',
|
'nickname' => 'nickname',
|
||||||
'phone' => ' 123456',
|
'phone' => ' 123456',
|
||||||
'hobby' => ['1', '2'],
|
|
||||||
'cityid' => '1',
|
'cityid' => '1',
|
||||||
'a' => 'a',
|
'a' => 'a',
|
||||||
'b' => 'b',
|
'b' => 'b',
|
||||||
@@ -166,11 +126,10 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
],
|
],
|
||||||
'username' => ['strtolower', 'callback'],
|
'username' => ['strtolower', 'callback'],
|
||||||
'password' => ['md5', 'callback'],
|
'password' => ['md5', 'callback'],
|
||||||
'nickname' => [[&$this, 'fillName'], 'callback', 'cn_'],
|
'nickname' => [[ & $this, 'fillName'], 'callback', 'cn_'],
|
||||||
'phone' => function ($value, $data) {
|
'phone' => function ($value, $data) {
|
||||||
return trim($value);
|
return trim($value);
|
||||||
},
|
},
|
||||||
'hobby' => ['', 'serialize'],
|
|
||||||
'cityid' => ['1', 'ignore'],
|
'cityid' => ['1', 'ignore'],
|
||||||
'address' => ['address'],
|
'address' => ['address'],
|
||||||
'integral' => 0,
|
'integral' => 0,
|
||||||
@@ -181,11 +140,10 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
'ab' => ['a,b', 'serialize'],
|
'ab' => ['a,b', 'serialize'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
\think\Config::set('auto', $auto);
|
Config::set('auto', $auto);
|
||||||
$result = $model->auto('user.edit')->create($data);
|
$result = $model->auto('user.edit')->create($data);
|
||||||
$data['nickname'] = 'cn_nickname';
|
$data['nickname'] = 'cn_nickname';
|
||||||
$data['phone'] = '123456';
|
$data['phone'] = '123456';
|
||||||
$data['hobby'] = serialize($data['hobby']);
|
|
||||||
$data['address'] = 'address';
|
$data['address'] = 'address';
|
||||||
$data['integral'] = 0;
|
$data['integral'] = 0;
|
||||||
$data['reg_time'] = time();
|
$data['reg_time'] = time();
|
||||||
@@ -194,31 +152,6 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
unset($data['cityid'], $data['a'], $data['b']);
|
unset($data['cityid'], $data['a'], $data['b']);
|
||||||
$this->assertEquals($data, $result);
|
$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)
|
public function fillName($value, $prefix)
|
||||||
@@ -366,7 +299,7 @@ EOF;
|
|||||||
$id = $result[0]['id'];
|
$id = $result[0]['id'];
|
||||||
$time = $result[0]['create_time'];
|
$time = $result[0]['create_time'];
|
||||||
$bind = ['create_time' => $time, 'status' => 1];
|
$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]]);
|
$info = $user_model->where(['create_time' => ':create_time'])->where(['status' => ':status'])->bind($bind)->field(true)->find(['cache' => ['key' => true]]);
|
||||||
$data = [
|
$data = [
|
||||||
'id' => $id,
|
'id' => $id,
|
||||||
'username' => 'test',
|
'username' => 'test',
|
||||||
@@ -411,7 +344,7 @@ EOF;
|
|||||||
];
|
];
|
||||||
$this->assertEquals($data, $result);
|
$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 = [
|
$data = [
|
||||||
['username' => 'test'],
|
['username' => 'test'],
|
||||||
['username' => 'test2'],
|
['username' => 'test2'],
|
||||||
@@ -422,7 +355,6 @@ EOF;
|
|||||||
$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);
|
$this->assertEquals($sql, $result);
|
||||||
|
|
||||||
|
|
||||||
$order_model = new Model('order', $this->getConfig());
|
$order_model = new Model('order', $this->getConfig());
|
||||||
|
|
||||||
$result = $order_model->field('user_id,sum(amount) amount')->group('user_id')->having('sum(amount) > 1000')->select();
|
$result = $order_model->field('user_id,sum(amount) amount')->group('user_id')->having('sum(amount) > 1000')->select();
|
||||||
@@ -464,10 +396,9 @@ EOF;
|
|||||||
];
|
];
|
||||||
$this->assertEquals($data, $result[0]);
|
$this->assertEquals($data, $result[0]);
|
||||||
|
|
||||||
|
|
||||||
$order_model = new Model('order', $config);
|
$order_model = new Model('order', $config);
|
||||||
$subsql = $order_model->limit(1)->buildSql();
|
$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();
|
$result = $user_model->alias('u')->join($subsql . ' o', 'u.id=o.user_id', 'left')->field('u.username,o.amount')->select();
|
||||||
$data = [
|
$data = [
|
||||||
'username' => 'test',
|
'username' => 'test',
|
||||||
'amount' => '200',
|
'amount' => '200',
|
||||||
|
|||||||
Reference in New Issue
Block a user