mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-07 07:12:47 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
3
base.php
3
base.php
@@ -23,9 +23,10 @@ defined('MODE_PATH') or define('MODE_PATH', THINK_PATH . 'mode' . DS); // 系统
|
|||||||
defined('CORE_PATH') or define('CORE_PATH', LIB_PATH . 'think' . DS);
|
defined('CORE_PATH') or define('CORE_PATH', LIB_PATH . 'think' . DS);
|
||||||
defined('TRAIT_PATH') or define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
|
defined('TRAIT_PATH') or define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
|
||||||
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
|
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
|
||||||
|
defined('ROOT_PATH') or define('ROOT_PATH', dirname(APP_PATH) . DS);
|
||||||
defined('APP_NAMESPACE') or define('APP_NAMESPACE', 'app');
|
defined('APP_NAMESPACE') or define('APP_NAMESPACE', 'app');
|
||||||
defined('COMMON_MODULE') or define('COMMON_MODULE', 'common');
|
defined('COMMON_MODULE') or define('COMMON_MODULE', 'common');
|
||||||
defined('RUNTIME_PATH') or define('RUNTIME_PATH', realpath(APP_PATH) . DS . 'runtime' . DS);
|
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
|
||||||
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
|
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
|
||||||
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
|
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
|
||||||
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
|
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ return [
|
|||||||
'default_controller' => 'Index',
|
'default_controller' => 'Index',
|
||||||
// 默认操作名
|
// 默认操作名
|
||||||
'default_action' => 'index',
|
'default_action' => 'index',
|
||||||
|
// 默认验证器
|
||||||
|
'default_validate' => '',
|
||||||
// 默认的空控制器名
|
// 默认的空控制器名
|
||||||
'empty_controller' => 'Error',
|
'empty_controller' => 'Error',
|
||||||
// 操作方法后缀
|
// 操作方法后缀
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ class App
|
|||||||
*/
|
*/
|
||||||
public static function run()
|
public static function run()
|
||||||
{
|
{
|
||||||
|
// 加载环境变量配置文件
|
||||||
|
Config::loadEnv(APP_PATH . 'env' . EXT);
|
||||||
|
|
||||||
// 初始化应用(公共模块)
|
// 初始化应用(公共模块)
|
||||||
self::initModule(COMMON_MODULE, Config::get());
|
self::initModule(COMMON_MODULE, Config::get());
|
||||||
|
|
||||||
@@ -130,6 +133,7 @@ class App
|
|||||||
break;
|
break;
|
||||||
case 'PUT':
|
case 'PUT':
|
||||||
parse_str(file_get_contents('php://input'), $vars);
|
parse_str(file_get_contents('php://input'), $vars);
|
||||||
|
$vars = array_merge($_GET, $vars);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$vars = $_GET;
|
$vars = $_GET;
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ class Config
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析配置文件或内容
|
* 解析配置文件或内容
|
||||||
*
|
|
||||||
* @param string $config 配置文件路径或内容
|
* @param string $config 配置文件路径或内容
|
||||||
* @param string $type 配置解析类型
|
* @param string $type 配置解析类型
|
||||||
* @param string $range 作用域
|
* @param string $range 作用域
|
||||||
@@ -46,7 +45,6 @@ class Config
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载配置文件(PHP格式)
|
* 加载配置文件(PHP格式)
|
||||||
*
|
|
||||||
* @param string $file 配置文件名
|
* @param string $file 配置文件名
|
||||||
* @param string $name 配置名(如设置即表示二级配置)
|
* @param string $name 配置名(如设置即表示二级配置)
|
||||||
* @param string $range 作用域
|
* @param string $range 作用域
|
||||||
@@ -63,9 +61,28 @@ class Config
|
|||||||
return is_file($file) ? self::set(include $file, $name, $range) : self::$config[$range];
|
return is_file($file) ? self::set(include $file, $name, $range) : self::$config[$range];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载环境变量配置文件
|
||||||
|
* @param string $file 配置文件名
|
||||||
|
* @param string $name 配置名(如设置即表示二级配置)
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function loadEnv($file, $name = '')
|
||||||
|
{
|
||||||
|
if (is_file($file)) {
|
||||||
|
$env = include $file;
|
||||||
|
foreach ($env as $key => $val) {
|
||||||
|
if (!empty($name)) {
|
||||||
|
$_ENV[ENV_PREFIX . $name . '_' . $key] = $val;
|
||||||
|
} else {
|
||||||
|
$_ENV[ENV_PREFIX . $key] = $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检测配置是否存在
|
* 检测配置是否存在
|
||||||
*
|
|
||||||
* @param string $name 配置参数名(支持二级配置 .号分割)
|
* @param string $name 配置参数名(支持二级配置 .号分割)
|
||||||
* @param string $range 作用域
|
* @param string $range 作用域
|
||||||
* @return bool
|
* @return bool
|
||||||
@@ -85,7 +102,6 @@ class Config
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取配置参数 为空则获取所有配置
|
* 获取配置参数 为空则获取所有配置
|
||||||
*
|
|
||||||
* @param string $name 配置参数名(支持二级配置 .号分割)
|
* @param string $name 配置参数名(支持二级配置 .号分割)
|
||||||
* @param string $range 作用域
|
* @param string $range 作用域
|
||||||
* @return mixed
|
* @return mixed
|
||||||
@@ -119,7 +135,6 @@ class Config
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置配置参数 name为数组则为批量设置
|
* 设置配置参数 name为数组则为批量设置
|
||||||
*
|
|
||||||
* @param string $name 配置参数名(支持二级配置 .号分割)
|
* @param string $name 配置参数名(支持二级配置 .号分割)
|
||||||
* @param mixed $value 配置值
|
* @param mixed $value 配置值
|
||||||
* @param string $range 作用域
|
* @param string $range 作用域
|
||||||
|
|||||||
@@ -147,21 +147,33 @@ class Controller
|
|||||||
* @param array $data 数据
|
* @param array $data 数据
|
||||||
* @param string|array $validate 验证器名或者验证规则数组
|
* @param string|array $validate 验证器名或者验证规则数组
|
||||||
* @param array $message 提示信息
|
* @param array $message 提示信息
|
||||||
|
* @param mixed $callback 回调方法(闭包)
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function validate($data, $validate, $message = [])
|
public function validate($data, $validate, $message = [], $callback = null)
|
||||||
{
|
{
|
||||||
if (is_array($validate)) {
|
if (is_array($validate)) {
|
||||||
$v = Loader::validate();
|
$v = Loader::validate(Config::get('default_validate'));
|
||||||
$v->rule($validate);
|
$v->rule($validate);
|
||||||
} else {
|
} else {
|
||||||
|
if (strpos($validate, '.')) {
|
||||||
|
// 支持场景
|
||||||
|
list($validate, $scene) = explode('.', $validate);
|
||||||
|
}
|
||||||
$v = Loader::validate($validate);
|
$v = Loader::validate($validate);
|
||||||
|
if (!empty($scene)) {
|
||||||
|
$v->scene($scene);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_array($message)) {
|
if (is_array($message)) {
|
||||||
$v->message($message);
|
$v->message($message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_callable($callback)) {
|
||||||
|
call_user_func_array($callback, [$v, &$data]);
|
||||||
|
}
|
||||||
|
|
||||||
if (!$v->check($data)) {
|
if (!$v->check($data)) {
|
||||||
return $v->getError();
|
return $v->getError();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ class Model
|
|||||||
protected $scope = [];
|
protected $scope = [];
|
||||||
// 字段映射定义
|
// 字段映射定义
|
||||||
protected $map = [];
|
protected $map = [];
|
||||||
// 字段验证规则定义
|
|
||||||
protected $rule = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 架构函数
|
* 架构函数
|
||||||
@@ -991,12 +989,18 @@ class Model
|
|||||||
if (!empty($this->options['validate'])) {
|
if (!empty($this->options['validate'])) {
|
||||||
$info = $this->options['validate'];
|
$info = $this->options['validate'];
|
||||||
if (is_array($info)) {
|
if (is_array($info)) {
|
||||||
$validate = Loader::validate();
|
$validate = Loader::validate(Config::get('default_validate'));
|
||||||
$validate->rule($info['rule']);
|
$validate->rule($info['rule']);
|
||||||
$validate->message($info['msg']);
|
$validate->message($info['msg']);
|
||||||
} else {
|
} else {
|
||||||
$name = is_string($info) ? $info : $this->name;
|
$name = is_string($info) ? $info : $this->name;
|
||||||
|
if (strpos($name, '.')) {
|
||||||
|
list($name, $scene) = explode('.', $name);
|
||||||
|
}
|
||||||
$validate = Loader::validate($name);
|
$validate = Loader::validate($name);
|
||||||
|
if (!empty($scene)) {
|
||||||
|
$validate->scene($scene);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!$validate->check($data)) {
|
if (!$validate->check($data)) {
|
||||||
$this->error = $validate->getError();
|
$this->error = $validate->getError();
|
||||||
@@ -1726,8 +1730,8 @@ class Model
|
|||||||
public function order($field, $order = null)
|
public function order($field, $order = null)
|
||||||
{
|
{
|
||||||
if (!empty($field)) {
|
if (!empty($field)) {
|
||||||
if (!is_array($field)) {
|
if (is_string($field)) {
|
||||||
$field = empty($order) ? [$field] : [(string) $field => (string) $order];
|
$field = empty($order) ? $field : [$field => $order];
|
||||||
}
|
}
|
||||||
$this->options['order'] = $field;
|
$this->options['order'] = $field;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,58 +32,52 @@ class Validate
|
|||||||
|
|
||||||
// 验证规则默认提示信息
|
// 验证规则默认提示信息
|
||||||
protected $typeMsg = [
|
protected $typeMsg = [
|
||||||
'require' => '不能为空',
|
'require' => ':attribute不能为空',
|
||||||
'number' => '必须是数字',
|
'number' => ':attribute必须是数字',
|
||||||
'float' => '必须是浮点数',
|
'float' => ':attribute必须是浮点数',
|
||||||
'boolean' => '必须是布尔值',
|
'boolean' => ':attribute必须是布尔值',
|
||||||
'email' => '格式不符',
|
'email' => ':attribute格式不符',
|
||||||
'array' => '必须是数组',
|
'array' => ':attribute必须是数组',
|
||||||
'accepted' => '必须是yes、on或者1',
|
'accepted' => ':attribute必须是yes、on或者1',
|
||||||
'date' => '格式不符合',
|
'date' => ':attribute格式不符合',
|
||||||
'alpha' => '只能是字母',
|
'alpha' => ':attribute只能是字母',
|
||||||
'alphaNum' => '只能是字母和数字',
|
'alphaNum' => ':attribute只能是字母和数字',
|
||||||
'alphaDash' => '只能是字母、数字和下划线_及破折号-',
|
'alphaDash' => ':attribute只能是字母、数字和下划线_及破折号-',
|
||||||
'activeUrl' => '不是有效的域名或者IP',
|
'activeUrl' => ':attribute不是有效的域名或者IP',
|
||||||
'url' => '不是有效的URL地址',
|
'url' => ':attribute不是有效的URL地址',
|
||||||
'ip' => '不是有效的IP地址',
|
'ip' => ':attribute不是有效的IP地址',
|
||||||
'dateFormat' => '必须使用日期格式 :rule',
|
'dateFormat' => ':attribute必须使用日期格式 :rule',
|
||||||
'in' => '必须在 :rule 范围内',
|
'in' => ':attribute必须在 :rule 范围内',
|
||||||
'notIn' => '不能在 :rule 范围内',
|
'notIn' => ':attribute不能在 :rule 范围内',
|
||||||
'between' => '只能在 :1 - :2 之间',
|
'between' => ':attribute只能在 :1 - :2 之间',
|
||||||
'notBetween' => '不能在 :1 - :2 之间',
|
'notBetween' => ':attribute不能在 :1 - :2 之间',
|
||||||
'length' => '长度不符合要求 :rule',
|
'length' => ':attribute长度不符合要求 :rule',
|
||||||
'max' => '长度不能超过 :rule',
|
'max' => ':attribute长度不能超过 :rule',
|
||||||
'min' => '长度不能小于 :rule',
|
'min' => ':attribute长度不能小于 :rule',
|
||||||
'after' => '日期不能小于 :rule',
|
'after' => ':attribute日期不能小于 :rule',
|
||||||
'before' => '日期不能超过 :rule',
|
'before' => ':attribute日期不能超过 :rule',
|
||||||
'expire' => '不在有效期内 :rule',
|
'expire' => '不在有效期内 :rule',
|
||||||
'allowIp' => '不允许的IP访问',
|
'allowIp' => '不允许的IP访问',
|
||||||
'denyIp' => '禁止的IP访问',
|
'denyIp' => '禁止的IP访问',
|
||||||
'confirm' => '和字段 :rule 不一致',
|
'confirm' => ':attribute和字段 :rule 不一致',
|
||||||
'egt' => '必须大于等于 :rule',
|
'egt' => ':attribute必须大于等于 :rule',
|
||||||
'gt' => '必须大于 :rule',
|
'gt' => ':attribute必须大于 :rule',
|
||||||
'elt' => '必须小于等于 :rule',
|
'elt' => ':attribute必须小于等于 :rule',
|
||||||
'lt' => '必须小于 :rule',
|
'lt' => ':attribute必须小于 :rule',
|
||||||
'eq' => '必须等于 :rule',
|
'eq' => ':attribute必须等于 :rule',
|
||||||
'unique' => '已存在',
|
'unique' => ':attribute已存在',
|
||||||
'regex' => '不符合指定规则',
|
'regex' => ':attribute不符合指定规则',
|
||||||
];
|
];
|
||||||
|
|
||||||
// 当前验证场景
|
// 当前验证场景
|
||||||
protected $scene = null;
|
protected $currentScene = null;
|
||||||
|
|
||||||
// 正则表达式 regex = ['zip'=>'\d{6}',...]
|
// 正则表达式 regex = ['zip'=>'\d{6}',...]
|
||||||
protected $regex = [];
|
protected $regex = [];
|
||||||
|
|
||||||
// 验证参数
|
// 验证场景 scene = ['edit'=>'name1,name2,...']
|
||||||
protected $config = [
|
protected $scene = [];
|
||||||
// 有值才验证 value_validate = [name1,name2,...]
|
|
||||||
'value_validate' => [],
|
|
||||||
// 存在就验证 exists_validate = [name1,name2,...]
|
|
||||||
'exists_validate' => [],
|
|
||||||
// 验证场景 scene = ['edit'=>'name1,name2,...']
|
|
||||||
'scene' => [],
|
|
||||||
];
|
|
||||||
// 验证失败错误信息
|
// 验证失败错误信息
|
||||||
protected $error = [];
|
protected $error = [];
|
||||||
|
|
||||||
@@ -95,19 +89,11 @@ class Validate
|
|||||||
* @access public
|
* @access public
|
||||||
* @param array $rules 验证规则
|
* @param array $rules 验证规则
|
||||||
* @param array $message 验证提示信息
|
* @param array $message 验证提示信息
|
||||||
* @param array $config 验证参数
|
|
||||||
*/
|
*/
|
||||||
public function __construct(array $rules = [], $message = [], $config = [])
|
public function __construct(array $rules = [], $message = [])
|
||||||
{
|
{
|
||||||
$this->rule = array_merge($this->rule, $rules);
|
$this->rule = array_merge($this->rule, $rules);
|
||||||
$this->message = array_merge($this->message, $message);
|
$this->message = array_merge($this->message, $message);
|
||||||
$this->config = array_merge($this->config, $config);
|
|
||||||
if (is_string($this->config['value_validate'])) {
|
|
||||||
$this->config['value_validate'] = explode(',', $this->config['value_validate']);
|
|
||||||
}
|
|
||||||
if (is_string($this->config['exists_validate'])) {
|
|
||||||
$this->config['exists_validate'] = explode(',', $this->config['exists_validate']);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,38 +180,23 @@ class Validate
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 传入验证参数
|
|
||||||
* @access public
|
|
||||||
* @param string|array $name 参数名或者数组
|
|
||||||
* @param mixed $value 参数值
|
|
||||||
* @return Validate
|
|
||||||
*/
|
|
||||||
public function config($name, $value = null)
|
|
||||||
{
|
|
||||||
if (is_array($name)) {
|
|
||||||
$this->config = array_merge($this->config, $name);
|
|
||||||
} else {
|
|
||||||
$this->config[$name] = $value;
|
|
||||||
}
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置验证场景
|
* 设置验证场景
|
||||||
* @access public
|
* @access public
|
||||||
* @param string $name 场景名
|
* @param string|array $name 场景名或者场景设置数组
|
||||||
* @param mixed $fields 要验证的字段
|
* @param mixed $fields 要验证的字段
|
||||||
* @return Validate
|
* @return Validate
|
||||||
*/
|
*/
|
||||||
public function scene($name, $fields = null)
|
public function scene($name, $fields = null)
|
||||||
{
|
{
|
||||||
if (is_null($fields)) {
|
if (is_array($name)) {
|
||||||
|
$this->scene = array_merge($this->scene, $name);
|
||||||
|
}if (is_null($fields)) {
|
||||||
// 设置当前场景
|
// 设置当前场景
|
||||||
$this->scene = $name;
|
$this->currentScene = $name;
|
||||||
} else {
|
} else {
|
||||||
// 设置验证场景
|
// 设置验证场景
|
||||||
$this->config['scene'][$name] = $fields;
|
$this->scene[$name] = $fields;
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -261,34 +232,43 @@ class Validate
|
|||||||
|
|
||||||
// 分析验证规则
|
// 分析验证规则
|
||||||
$scene = $this->getScene($scene);
|
$scene = $this->getScene($scene);
|
||||||
// 读取提示信息
|
|
||||||
if (isset($rules['__message__'])) {
|
|
||||||
$this->message($rules['__message__']);
|
|
||||||
unset($rules['__message__']);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($rules as $key => $rule) {
|
foreach ($rules as $key => $item) {
|
||||||
|
// field => rule1|rule2... field=>['rule1','rule2',...]
|
||||||
|
if (is_numeric($key)) {
|
||||||
|
// [field,rule1|rule2,msg1|msg2]
|
||||||
|
$key = $item[0];
|
||||||
|
$rule = $item[1];
|
||||||
|
if (isset($item[2])) {
|
||||||
|
$msg = is_string($item[2]) ? explode('|', $item[2]) : $item[2];
|
||||||
|
} else {
|
||||||
|
$msg = [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$rule = $item;
|
||||||
|
$msg = [];
|
||||||
|
}
|
||||||
if (strpos($key, '|')) {
|
if (strpos($key, '|')) {
|
||||||
// 支持 字段|描述 用于返回默认错误
|
// 字段|描述 用于指定属性名称
|
||||||
list($key, $title) = explode('|', $key);
|
list($key, $title) = explode('|', $key);
|
||||||
} else {
|
} else {
|
||||||
$title = $key;
|
$title = $key;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 场景检测
|
// 场景检测
|
||||||
if (!empty($scene) && !in_array($key, $scene)) {
|
if (!empty($scene)) {
|
||||||
continue;
|
if ($scene instanceof \Closure && !call_user_func_array($scene, [$key, &$data])) {
|
||||||
|
continue;
|
||||||
|
} elseif (is_array($scene) && !in_array($key, $scene)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取数据 支持二维数组
|
// 获取数据 支持二维数组
|
||||||
$value = $this->getDataValue($data, $key);
|
$value = $this->getDataValue($data, $key);
|
||||||
|
|
||||||
if ((isset($this->config['value_validate']) && in_array($key, $this->config['value_validate']) && '' == $value)
|
// 字段验证
|
||||||
|| (isset($this->config['exists_validate']) && in_array($key, $this->config['exists_validate']) && is_null($value))) {
|
$result = $this->checkItem($key, $value, $rule, $data, $title, $msg);
|
||||||
// 不满足自动验证条件
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 验证字段规则
|
|
||||||
$result = $this->checkItem($key, $value, $rule, $data, $title);
|
|
||||||
|
|
||||||
if (true !== $result) {
|
if (true !== $result) {
|
||||||
// 没有返回true 则表示验证失败
|
// 没有返回true 则表示验证失败
|
||||||
@@ -316,9 +296,10 @@ class Validate
|
|||||||
* @param mixed $rules 验证规则
|
* @param mixed $rules 验证规则
|
||||||
* @param array $data 数据
|
* @param array $data 数据
|
||||||
* @param string $title 字段描述
|
* @param string $title 字段描述
|
||||||
* @return string|true
|
* @param array $msg 提示信息
|
||||||
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
protected function checkItem($field, $value, $rules, &$data, $title = '')
|
protected function checkItem($field, $value, $rules, &$data, $title = '', $msg = [])
|
||||||
{
|
{
|
||||||
if ($rules instanceof \Closure) {
|
if ($rules instanceof \Closure) {
|
||||||
// 匿名函数验证 支持传入当前字段和所有字段两个数据
|
// 匿名函数验证 支持传入当前字段和所有字段两个数据
|
||||||
@@ -328,7 +309,7 @@ class Validate
|
|||||||
if (is_string($rules)) {
|
if (is_string($rules)) {
|
||||||
$rules = explode('|', $rules);
|
$rules = explode('|', $rules);
|
||||||
}
|
}
|
||||||
$error = [];
|
$i = 0;
|
||||||
foreach ($rules as $key => $rule) {
|
foreach ($rules as $key => $rule) {
|
||||||
if ($rule instanceof \Closure) {
|
if ($rule instanceof \Closure) {
|
||||||
$result = call_user_func_array($rule, [$value, &$data]);
|
$result = call_user_func_array($rule, [$value, &$data]);
|
||||||
@@ -347,34 +328,34 @@ class Validate
|
|||||||
} else {
|
} else {
|
||||||
$info = $type = $key;
|
$info = $type = $key;
|
||||||
}
|
}
|
||||||
// 验证类型
|
|
||||||
$callback = isset($this->type[$type]) ? $this->type[$type] : [$this, $type];
|
// 如果不是require 有数据才会行验证
|
||||||
// 验证数据
|
if (0 === strpos($info, 'require') || !empty($value)) {
|
||||||
$result = call_user_func_array($callback, [$value, $rule, &$data, $field]);
|
// 验证类型
|
||||||
|
$callback = isset($this->type[$type]) ? $this->type[$type] : [$this, $type];
|
||||||
|
// 验证数据
|
||||||
|
$result = call_user_func_array($callback, [$value, $rule, &$data, $field]);
|
||||||
|
} else {
|
||||||
|
$result = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (false === $result) {
|
if (false === $result) {
|
||||||
// 验证失败 返回错误信息
|
// 验证失败 返回错误信息
|
||||||
if (isset($this->message[$field . '.' . $info])) {
|
if (isset($msg[$i])) {
|
||||||
$error[] = $this->message[$field . '.' . $info];
|
$message = $msg[$i];
|
||||||
} elseif (isset($this->message[$field . '.'])) {
|
|
||||||
$error[] = $this->message[$field . '.'];
|
|
||||||
} else {
|
} else {
|
||||||
$error[] = $this->getTypeMsg($title ?: $field, $info, $rule);
|
$message = $this->getRuleMsg($field, $title, $info, $rule);
|
||||||
}
|
}
|
||||||
} elseif (is_string($result)) {
|
return $message;
|
||||||
$error[] = $result;
|
} elseif (true !== $result) {
|
||||||
} elseif (is_array($result)) {
|
// 返回自定义错误信息
|
||||||
// 自定义错误信息数组
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
$i++;
|
||||||
if (!empty($error)) {
|
|
||||||
$result = implode(',', $error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 验证失败返回错误信息
|
return true !== $result ? $result : true;
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -541,26 +522,38 @@ class Validate
|
|||||||
* 验证是否唯一
|
* 验证是否唯一
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param mixed $value 字段值
|
* @param mixed $value 字段值
|
||||||
* @param mixed $rule 验证规则 格式:数据表,字段名,排除ID
|
* @param mixed $rule 验证规则 格式:数据表,字段名,排除ID,主键名
|
||||||
* @param array $data 数据
|
* @param array $data 数据
|
||||||
* @param string $field 验证字段名
|
* @param string $field 验证字段名
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function unique($value, $rule, $data, $field)
|
protected function unique($value, $rule, $data, $field)
|
||||||
{
|
{
|
||||||
$rule = explode(',', $rule);
|
if (is_string($rule)) {
|
||||||
|
$rule = explode(',', $rule);
|
||||||
|
}
|
||||||
$model = Loader::table($rule[0]);
|
$model = Loader::table($rule[0]);
|
||||||
$key = isset($rule[3]) ? $rule[3] : $model->getPk();
|
|
||||||
$field = isset($rule[1]) ? $rule[1] : $field;
|
$field = isset($rule[1]) ? $rule[1] : $field;
|
||||||
|
|
||||||
|
if (strpos($field, '^')) {
|
||||||
|
// 支持多个字段验证
|
||||||
|
$fields = explode('^', $field);
|
||||||
|
foreach ($fields as $field) {
|
||||||
|
$map[$field] = $data[$field];
|
||||||
|
}
|
||||||
|
} elseif (strpos($field, '=')) {
|
||||||
|
parse_str($field, $map);
|
||||||
|
} else {
|
||||||
|
$map[$field] = $data[$field];
|
||||||
|
}
|
||||||
|
|
||||||
|
$key = strval(isset($rule[3]) ? $rule[3] : $model->getPk());
|
||||||
if (isset($rule[2])) {
|
if (isset($rule[2])) {
|
||||||
$except = $rule[2];
|
$map[$key] = ['neq', $rule[2]];
|
||||||
} elseif (isset($data[$key])) {
|
} elseif (isset($data[$key])) {
|
||||||
$except = $data[$key];
|
$map[$key] = ['neq', $data[$key]];
|
||||||
}
|
|
||||||
$map[$field] = $value;
|
|
||||||
if (isset($except)) {
|
|
||||||
$map[$key] = ['neq', $except];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($model->where($map)->field($key)->find()) {
|
if ($model->where($map)->field($key)->find()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -589,18 +582,18 @@ class Validate
|
|||||||
*/
|
*/
|
||||||
protected function filter($value, $rule)
|
protected function filter($value, $rule)
|
||||||
{
|
{
|
||||||
if (is_int($rule)) {
|
if (is_string($rule) && strpos($rule, ',')) {
|
||||||
$param = null;
|
|
||||||
} elseif (is_string($rule) && strpos($rule, ',')) {
|
|
||||||
list($rule, $param) = explode(',', $rule);
|
list($rule, $param) = explode(',', $rule);
|
||||||
} elseif (is_array($rule)) {
|
} elseif (is_array($rule)) {
|
||||||
$param = isset($rule[1]) ? $rule[1] : null;
|
$param = isset($rule[1]) ? $rule[1] : null;
|
||||||
|
} else {
|
||||||
|
$param = null;
|
||||||
}
|
}
|
||||||
return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
|
return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证某个字段的值等于某个值的时候必须
|
* 验证某个字段等于某个值的时候必须
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param mixed $value 字段值
|
* @param mixed $value 字段值
|
||||||
* @param mixed $rule 验证规则
|
* @param mixed $rule 验证规则
|
||||||
@@ -617,6 +610,24 @@ class Validate
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证某个字段有值的情况下必须
|
||||||
|
* @access protected
|
||||||
|
* @param mixed $value 字段值
|
||||||
|
* @param mixed $rule 验证规则
|
||||||
|
* @param array $data 数据
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function requireWith($value, $rule, $data)
|
||||||
|
{
|
||||||
|
$val = $this->getDataValue($data, $rule);
|
||||||
|
if (!empty($val)) {
|
||||||
|
return !empty($value);
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证是否在范围内
|
* 验证是否在范围内
|
||||||
* @access protected
|
* @access protected
|
||||||
@@ -835,28 +846,39 @@ class Validate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取验证规则的默认提示信息
|
* 获取验证规则的错误提示信息
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param string $attribute 字段名称
|
* @param string $attribute 字段英文名
|
||||||
* @param string $type 验证类型名称
|
* @param string $title 字段描述名
|
||||||
* @param mixed $rule 验证规则
|
* @param string $type 验证规则名称
|
||||||
|
* @param mixed $rule 验证规则数据
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function getTypeMsg($attribute, $type, $rule)
|
protected function getRuleMsg($attribute, $title, $type, $rule)
|
||||||
{
|
{
|
||||||
if (isset($this->typeMsg[$type])) {
|
if (isset($this->message[$attribute . '.' . $type])) {
|
||||||
|
$msg = $this->message[$attribute . '.' . $type];
|
||||||
|
} elseif (isset($this->message[$attribute])) {
|
||||||
|
$msg = $this->message[$attribute];
|
||||||
|
} elseif (isset($this->typeMsg[$type])) {
|
||||||
|
$msg = $this->typeMsg[$type];
|
||||||
|
} else {
|
||||||
|
$msg = $title . '规则错误';
|
||||||
|
}
|
||||||
|
// TODO 多语言支持
|
||||||
|
if (is_string($msg) && false !== strpos($msg, ':')) {
|
||||||
|
// 变量替换
|
||||||
if (strpos($rule, ',')) {
|
if (strpos($rule, ',')) {
|
||||||
$array = array_pad(explode(',', $rule), 3, '');
|
$array = array_pad(explode(',', $rule), 3, '');
|
||||||
} else {
|
} else {
|
||||||
$array = array_pad([], 3, '');
|
$array = array_pad([], 3, '');
|
||||||
}
|
}
|
||||||
return (false === strpos($this->typeMsg[$type], ':attribute') ? $attribute : '') . str_replace(
|
$msg = str_replace(
|
||||||
[':rule', ':attribute', ':1', ':2', ':3'],
|
[':attribute', ':rule', ':1', ':2', ':3'],
|
||||||
[(string) $rule, $attribute, $array[0], $array[1], $array[2]],
|
[$title, (string) $rule, $array[0], $array[1], $array[2]],
|
||||||
$this->typeMsg[$type]);
|
$msg);
|
||||||
} else {
|
|
||||||
return $attribute . '规则错误';
|
|
||||||
}
|
}
|
||||||
|
return $msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -869,12 +891,12 @@ class Validate
|
|||||||
{
|
{
|
||||||
if (empty($scene)) {
|
if (empty($scene)) {
|
||||||
// 读取指定场景
|
// 读取指定场景
|
||||||
$scene = $this->scene;
|
$scene = $this->currentScene;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!empty($scene) && isset($this->config['scene'][$scene])) {
|
if (!empty($scene) && isset($this->scene[$scene])) {
|
||||||
// 如果设置了验证适用场景
|
// 如果设置了验证适用场景
|
||||||
$scene = $this->config['scene'][$scene];
|
$scene = $this->scene[$scene];
|
||||||
if (is_string($scene)) {
|
if (is_string($scene)) {
|
||||||
$scene = explode(',', $scene);
|
$scene = explode(',', $scene);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,8 +53,9 @@ class File
|
|||||||
} else {
|
} else {
|
||||||
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||||
}
|
}
|
||||||
$runtime = number_format(microtime(true) - START_TIME, 6);
|
$runtime = microtime(true) - START_TIME;
|
||||||
$reqs = number_format(1 / $runtime, 2);
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$runtime = number_format($runtime, 6);
|
||||||
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||||
|
|||||||
@@ -41,8 +41,9 @@ class Sae
|
|||||||
} else {
|
} else {
|
||||||
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
|
||||||
}
|
}
|
||||||
$runtime = number_format(microtime(true) - START_TIME, 6);
|
$runtime = microtime(true) - START_TIME;
|
||||||
$reqs = number_format(1 / $runtime, 2);
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$runtime = number_format($runtime, 6);
|
||||||
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||||
|
|||||||
@@ -59,8 +59,9 @@ class Socket
|
|||||||
if (!$this->check()) {
|
if (!$this->check()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$runtime = number_format(microtime(true) - START_TIME, 6);
|
$runtime = microtime(true) - START_TIME;
|
||||||
$reqs = number_format(1 / $runtime, 2);
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$runtime = number_format($runtime, 6);
|
||||||
$time_str = " [运行时间:{$runtime}s][吞吐率:{$reqs}req/s]";
|
$time_str = " [运行时间:{$runtime}s][吞吐率:{$reqs}req/s]";
|
||||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||||
|
|||||||
@@ -43,8 +43,9 @@ class Trace
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 获取基本信息
|
// 获取基本信息
|
||||||
$runtime = number_format(microtime(true) - START_TIME, 6);
|
$runtime = microtime(true) - START_TIME;
|
||||||
$reqs = number_format(1 / $runtime, 2);
|
$reqs = number_format(1 / $runtime, 2);
|
||||||
|
$runtime = number_format($runtime, 6);
|
||||||
$mem = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
$mem = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||||
|
|
||||||
// 页面Trace信息
|
// 页面Trace信息
|
||||||
|
|||||||
@@ -31,28 +31,31 @@ trait View
|
|||||||
{
|
{
|
||||||
if (empty($this->trueTableName)) {
|
if (empty($this->trueTableName)) {
|
||||||
$tableName = '';
|
$tableName = '';
|
||||||
foreach ($this->viewFields as $key => $view) {
|
$len = 0;
|
||||||
|
foreach ($this->viewFields as $name => $view) {
|
||||||
// 获取数据表名称
|
// 获取数据表名称
|
||||||
if (isset($view['_table'])) {
|
if (isset($view['_table'])) {
|
||||||
// 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图
|
// 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图
|
||||||
$tableName .= $view['_table'];
|
$tableName .= $view['_table'];
|
||||||
} else {
|
} else {
|
||||||
$class = $key . 'Model';
|
$tableName .= \think\Loader::model($name)->getTableName();
|
||||||
$model = class_exists($class) ? new $class() : M($key);
|
|
||||||
$tableName .= $model->getTableName();
|
|
||||||
}
|
}
|
||||||
// 表别名定义
|
// 表别名定义
|
||||||
$tableName .= !empty($view['_as']) ? ' ' . $view['_as'] : ' ' . $key;
|
$tableName .= !empty($view['_as']) ? ' ' . $view['_as'] : ' ' . $name;
|
||||||
// 支持ON 条件定义
|
// 支持ON 条件定义
|
||||||
$tableName .= !empty($view['_on']) ? ' ON ' . $view['_on'] : '';
|
$tableName .= !empty($view['_on']) ? ' ON ' . $view['_on'] : '';
|
||||||
// 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
|
if (!empty($view['_type'])) {
|
||||||
$type = !empty($view['_type']) ? $view['_type'] : '';
|
// 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
|
||||||
$tableName .= ' ' . strtoupper($type) . ' JOIN ';
|
$type = strtoupper($view['_type']);
|
||||||
$len = strlen($type . '_JOIN ');
|
$tableName .= ' ' . $type . ' JOIN ';
|
||||||
|
if ($view == end($this->viewFields)) {
|
||||||
|
$len = strlen($type) + 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$tableName = substr($tableName, 0, -$len);
|
$this->trueTableName = $len ? substr($tableName, 0, -$len) : $tableName;
|
||||||
$this->trueTableName = $tableName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->trueTableName;
|
return $this->trueTableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,26 +67,43 @@ trait View
|
|||||||
*/
|
*/
|
||||||
protected function _options_filter(&$options)
|
protected function _options_filter(&$options)
|
||||||
{
|
{
|
||||||
if (isset($options['field'])) {
|
$viewFields = [];
|
||||||
$options['field'] = $this->checkFields($options['field']);
|
foreach ($this->viewFields as $name => $val) {
|
||||||
} else {
|
$k = isset($val['_as']) ? $val['_as'] : $name;
|
||||||
$options['field'] = $this->checkFields();
|
$val = $this->_checkFields($name, $val);
|
||||||
|
foreach ($val as $key => $field) {
|
||||||
|
if (is_numeric($key)) {
|
||||||
|
$viewFields[$k . '.' . $field] = $field;
|
||||||
|
} elseif ('_' != substr($key, 0, 1)) {
|
||||||
|
// 以_开头的为特殊定义
|
||||||
|
if (false !== strpos($key, '*') || false !== strpos($key, '(') || false !== strpos($key, '.')) {
|
||||||
|
//如果包含* 或者 使用了sql方法 则不再添加前面的表名
|
||||||
|
$viewFields[$key] = $field;
|
||||||
|
} else {
|
||||||
|
$viewFields[$k . '.' . $key] = $field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (empty($options['field'])) {
|
||||||
|
$options['field'] = '*';
|
||||||
|
}
|
||||||
|
$options['field'] = $this->checkFields($options['field'], $viewFields);
|
||||||
if (isset($options['group'])) {
|
if (isset($options['group'])) {
|
||||||
$options['group'] = $this->checkGroup($options['group']);
|
$options['group'] = $this->checkGroup($options['group'], $viewFields);
|
||||||
}
|
}
|
||||||
if (isset($options['where'])) {
|
if (isset($options['where'])) {
|
||||||
$options['where'] = $this->checkCondition($options['where']);
|
$options['where'] = $this->checkCondition($options['where'], $viewFields);
|
||||||
}
|
}
|
||||||
if (isset($options['order'])) {
|
if (isset($options['order'])) {
|
||||||
$options['order'] = $this->checkOrder($options['order']);
|
$options['order'] = $this->checkOrder($options['order'], $viewFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否定义了所有字段
|
* 检查是否定义了所有字段
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param string $name 模型名称
|
* @param string $name 模型名称
|
||||||
* @param array $fields 字段数组
|
* @param array $fields 字段数组
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
@@ -94,161 +114,143 @@ trait View
|
|||||||
$fields = array_merge($fields, \think\Loader::model($name)->getFields());
|
$fields = array_merge($fields, \think\Loader::model($name)->getFields());
|
||||||
unset($fields[$pos]);
|
unset($fields[$pos]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查条件中的视图字段
|
* 检查条件中的视图字段
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param mixed $data 条件表达式
|
* @param mixed $data 条件表达式
|
||||||
|
* @param array $fields 视图字段数组
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function checkCondition($where)
|
protected function checkCondition($where, $viewFields)
|
||||||
{
|
{
|
||||||
if (is_array($where)) {
|
if (is_array($where)) {
|
||||||
$view = [];
|
$_where = [];
|
||||||
// 检查视图字段
|
foreach ($where as $field => $value) {
|
||||||
foreach ($this->viewFields as $key => $val) {
|
if (false !== $k = array_search($field, $viewFields, true)) {
|
||||||
$k = isset($val['_as']) ? $val['_as'] : $key;
|
// 存在视图字段
|
||||||
$val = $this->_checkFields($key, $val);
|
$_where[$k] = $value;
|
||||||
foreach ($where as $name => $value) {
|
} else {
|
||||||
if (false !== $field = array_search($name, $val, true)) {
|
$_where[$field] = $value;
|
||||||
// 存在视图字段
|
|
||||||
$_key = is_numeric($field) ? $k . '.' . $name : $k . '.' . $field;
|
|
||||||
$view[$_key] = $value;
|
|
||||||
unset($where[$name]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$where = array_merge($where, $view);
|
return $_where;
|
||||||
|
} else {
|
||||||
|
return $where;
|
||||||
}
|
}
|
||||||
return $where;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查Order表达式中的视图字段
|
* 检查Order表达式中的视图字段
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param string $order 字段
|
* @param string|array $order 字段
|
||||||
|
* @param array $fields 视图字段数组
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function checkOrder($order = '')
|
protected function checkOrder($order = '', $viewFields)
|
||||||
{
|
{
|
||||||
if (is_string($order) && !empty($order)) {
|
if (empty($order)) {
|
||||||
$orders = explode(',', $order);
|
return '';
|
||||||
$_order = [];
|
} elseif (is_string($order)) {
|
||||||
foreach ($orders as $order) {
|
$order = explode(',', $order);
|
||||||
$array = explode(' ', $order);
|
|
||||||
$field = $array[0];
|
|
||||||
$sort = isset($array[1]) ? $array[1] : 'ASC';
|
|
||||||
// 解析成视图字段
|
|
||||||
foreach ($this->viewFields as $name => $val) {
|
|
||||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
|
||||||
$val = $this->_checkFields($name, $val);
|
|
||||||
if (false !== $_field = array_search($field, $val, true)) {
|
|
||||||
// 存在视图字段
|
|
||||||
$field = is_numeric($_field) ? $k . '.' . $field : $k . '.' . $_field;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$_order[] = $field . ' ' . $sort;
|
|
||||||
}
|
|
||||||
$order = implode(',', $_order);
|
|
||||||
}
|
}
|
||||||
return $order;
|
$_order = [];
|
||||||
|
foreach ($order as $key => $field) {
|
||||||
|
if (is_numeric($key)) {
|
||||||
|
if ($pos = strpos($field, ' ')) {
|
||||||
|
$sort = substr($field, $pos);
|
||||||
|
$field = substr($field, 0, $pos);
|
||||||
|
} else {
|
||||||
|
$sort = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$sort = ' ' . $field;
|
||||||
|
$field = $key;
|
||||||
|
}
|
||||||
|
if (false !== $k = array_search($field, $viewFields, true)) {
|
||||||
|
// 存在视图字段
|
||||||
|
$field = $k . $sort;
|
||||||
|
}
|
||||||
|
$_order[] = $field;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $_order;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查Group表达式中的视图字段
|
* 检查Group表达式中的视图字段
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param string $group 字段
|
* @param string $group 字段
|
||||||
|
* @param array $fields 视图字段数组
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function checkGroup($group = '')
|
protected function checkGroup($group = '', $viewFields)
|
||||||
{
|
{
|
||||||
if (!empty($group)) {
|
if (empty($group)) {
|
||||||
$groups = explode(',', $group);
|
return '';
|
||||||
$_group = [];
|
} elseif (is_string($group)) {
|
||||||
foreach ($groups as $field) {
|
$group = explode(',', $group);
|
||||||
// 解析成视图字段
|
|
||||||
foreach ($this->viewFields as $name => $val) {
|
|
||||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
|
||||||
$val = $this->_checkFields($name, $val);
|
|
||||||
if (false !== $_field = array_search($field, $val, true)) {
|
|
||||||
// 存在视图字段
|
|
||||||
$field = is_numeric($_field) ? $k . '.' . $field : $k . '.' . $_field;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$_group[] = $field;
|
|
||||||
}
|
|
||||||
$group = implode(',', $_group);
|
|
||||||
}
|
}
|
||||||
return $group;
|
foreach ($group as &$field) {
|
||||||
|
if (false !== $k = array_search($field, $viewFields, true)) {
|
||||||
|
// 存在视图字段
|
||||||
|
$field = $k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(',', $group);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查fields表达式中的视图字段
|
* 检查fields表达式中的视图字段
|
||||||
* @access protected
|
* @access protected
|
||||||
* @param string $fields 字段
|
* @param string $fields 字段
|
||||||
|
* @param array $fields 视图字段数组
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function checkFields($fields = '')
|
protected function checkFields($fields = '*', $viewFields)
|
||||||
{
|
{
|
||||||
if (empty($fields) || '*' == $fields) {
|
var_dump($fields);
|
||||||
// 获取全部视图字段
|
if (is_string($fields)) {
|
||||||
$fields = [];
|
if ('*' == $fields) {
|
||||||
foreach ($this->viewFields as $name => $val) {
|
return $viewFields;
|
||||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
} else {
|
||||||
$val = $this->_checkFields($name, $val);
|
|
||||||
foreach ($val as $key => $field) {
|
|
||||||
if (is_numeric($key)) {
|
|
||||||
$fields[] = $k . '.' . $field . ' AS ' . $field;
|
|
||||||
} elseif ('_' != substr($key, 0, 1)) {
|
|
||||||
// 以_开头的为特殊定义
|
|
||||||
if (false !== strpos($key, '*') || false !== strpos($key, '(') || false !== strpos($key, '.')) {
|
|
||||||
//如果包含* 或者 使用了sql方法 则不再添加前面的表名
|
|
||||||
$fields[] = $key . ' AS ' . $field;
|
|
||||||
} else {
|
|
||||||
$fields[] = $k . '.' . $key . ' AS ' . $field;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$fields = implode(',', $fields);
|
|
||||||
} else {
|
|
||||||
if (!is_array($fields)) {
|
|
||||||
$fields = explode(',', $fields);
|
$fields = explode(',', $fields);
|
||||||
}
|
}
|
||||||
// 解析成视图字段
|
}
|
||||||
$array = [];
|
$_fields = [];
|
||||||
foreach ($fields as $key => $field) {
|
foreach ($fields as $key => $field) {
|
||||||
if (strpos($field, '(') || strpos(strtolower($field), ' as ')) {
|
if (is_numeric($key)) {
|
||||||
// 使用了函数或者别名
|
if ($pos = strpos($field, ' ')) {
|
||||||
$array[] = $field;
|
$alias = substr($field, $pos);
|
||||||
unset($fields[$key]);
|
$field = substr($field, 0, $pos);
|
||||||
|
} else {
|
||||||
|
$alias = ' AS ' . $field;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
$alias = ' AS ' . $field;
|
||||||
|
$field = $key;
|
||||||
}
|
}
|
||||||
foreach ($this->viewFields as $name => $val) {
|
if (strpos($field, '(')) {
|
||||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
if (preg_match_all('/(?<!\s)\b(\w+)\b(?![\.\(])/', $field, $matches, PREG_OFFSET_CAPTURE)) {
|
||||||
$val = $this->_checkFields($name, $val);
|
// 倒序找出的字段数组,以便从后向前替换
|
||||||
foreach ($fields as $key => $field) {
|
$items = array_reverse($matches[0]);
|
||||||
if (false !== $_field = array_search($field, $val, true)) {
|
foreach ($items as $item) {
|
||||||
// 存在视图字段
|
if (false !== $k = array_search($item[0], $viewFields, true)) {
|
||||||
if (is_numeric($_field)) {
|
$field = substr_replace($field, $k, $item[1], strlen($item[0]));
|
||||||
$array[] = $k . '.' . $field . ' AS ' . $field;
|
|
||||||
} elseif ('_' != substr($_field, 0, 1)) {
|
|
||||||
if (false !== strpos($_field, '*') || false !== strpos($_field, '(') || false !== strpos($_field, '.')) {
|
|
||||||
//如果包含* 或者 使用了sql方法 则不再添加前面的表名
|
|
||||||
$array[] = $_field . ' AS ' . $field;
|
|
||||||
} else {
|
|
||||||
$array[] = $k . '.' . $_field . ' AS ' . $field;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} elseif (false !== $k = array_search($field, $viewFields, true)) {
|
||||||
|
// 存在视图字段
|
||||||
|
$field = $k . $alias;
|
||||||
}
|
}
|
||||||
$fields = implode(',', $array);
|
$_fields[] = $field;
|
||||||
}
|
}
|
||||||
return $fields;
|
|
||||||
|
return $_fields;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ class controllerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$viewFetch = $view->fetch($template, ['name' => 'ThinkPHP']);
|
$viewFetch = $view->fetch($template, ['name' => 'ThinkPHP']);
|
||||||
$controllerFetch = $controller->fetch($template, ['name' => 'ThinkPHP']);
|
$controllerFetch = $controller->fetch($template, ['name' => 'ThinkPHP']);
|
||||||
$this->assertEquals($controllerFetch, $viewFetch);
|
$this->assertEquals($controllerFetch, $viewFetch);
|
||||||
|
$controllerFetch = $controller->display($template, ['name' => 'ThinkPHP']);
|
||||||
|
$this->assertEquals($controllerFetch, $viewFetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testShow()
|
public function testShow()
|
||||||
@@ -155,4 +157,31 @@ class controllerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$controller->engine('php');
|
$controller->engine('php');
|
||||||
$this->assertEquals('php', $view->engine);
|
$this->assertEquals('php', $view->engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testValidate()
|
||||||
|
{
|
||||||
|
$controller = new Foo;
|
||||||
|
$data = [
|
||||||
|
'username' => 'username',
|
||||||
|
'nickname' => 'nickname',
|
||||||
|
'password' => '123456',
|
||||||
|
'repassword' => '123456',
|
||||||
|
'email' => 'abc@abc.com',
|
||||||
|
'sex' => '0',
|
||||||
|
'age' => '20',
|
||||||
|
'code' => '1234',
|
||||||
|
];
|
||||||
|
|
||||||
|
$validate = [
|
||||||
|
['username', 'length:5,15', '用户名长度为5到15个字符'],
|
||||||
|
['nickname', 'require', '请填昵称'],
|
||||||
|
['password', '[\w-]{6,15}', '密码长度为6到15个字符'],
|
||||||
|
['repassword', 'confirm:password', '两次密码不一到致'],
|
||||||
|
['email', 'filter:validate_email', '邮箱格式错误'],
|
||||||
|
['sex', 'in:0,1', '性别只能为为男或女'],
|
||||||
|
['age', 'between:1,80', '年龄只能在10-80之间'],
|
||||||
|
];
|
||||||
|
$result = $controller->validate($data, $validate);
|
||||||
|
$this->assertTrue($result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
28
tests/thinkphp/library/think/dbTest.php
Normal file
28
tests/thinkphp/library/think/dbTest.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?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>
|
||||||
|
// +----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Db类测试
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace tests\thinkphp\library\think;
|
||||||
|
|
||||||
|
use \think\Db;
|
||||||
|
|
||||||
|
class dbTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
public function testConnect()
|
||||||
|
{
|
||||||
|
Db::connect('mysql://root@127.0.0.1/test#utf8');
|
||||||
|
Db::execute('show databases');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -118,7 +118,7 @@ class debugTest extends \PHPUnit_Framework_TestCase
|
|||||||
{
|
{
|
||||||
$useMem = Debug::getUseMem();
|
$useMem = Debug::getUseMem();
|
||||||
|
|
||||||
$this->assertLessThan(20, explode(" ", $useMem)[0]);
|
$this->assertLessThan(30, explode(" ", $useMem)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,7 +135,7 @@ class debugTest extends \PHPUnit_Framework_TestCase
|
|||||||
$str .= "mem";
|
$str .= "mem";
|
||||||
}
|
}
|
||||||
$memPeak = Debug::getMemPeak($start, $end);
|
$memPeak = Debug::getMemPeak($start, $end);
|
||||||
$this->assertLessThan(400, explode(" ", $memPeak)[0]);
|
$this->assertLessThan(500, explode(" ", $memPeak)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,6 +42,30 @@ class loaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(true, Loader::autoload('top\test\Hello'));
|
$this->assertEquals(true, Loader::autoload('top\test\Hello'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testAddNamespaceAlias()
|
||||||
|
{
|
||||||
|
Loader::addNamespaceAlias('top', 'top\test');
|
||||||
|
Loader::addNamespaceAlias(['top' => 'top\test', 'app' => 'app\index']);
|
||||||
|
//$this->assertEquals(true, Loader::autoload('top\Hello'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTable()
|
||||||
|
{
|
||||||
|
Loader::table('', [
|
||||||
|
'connection' => [
|
||||||
|
'type' => 'mysql',
|
||||||
|
'database' => 'test',
|
||||||
|
'username' => 'root',
|
||||||
|
'password' => '',
|
||||||
|
]]);
|
||||||
|
Loader::db('mysql://root@127.0.0.1/test#utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testInstance()
|
||||||
|
{
|
||||||
|
Loader::instance('\think\Validate');
|
||||||
|
}
|
||||||
|
|
||||||
public function testImport()
|
public function testImport()
|
||||||
{
|
{
|
||||||
$this->assertEquals(true, Loader::import('think.log.driver.Sae'));
|
$this->assertEquals(true, Loader::import('think.log.driver.Sae'));
|
||||||
|
|||||||
@@ -36,62 +36,30 @@ class modelTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testValidate()
|
public function testValidate()
|
||||||
{
|
{
|
||||||
/*
|
$model = new Model('', $this->getConfig());
|
||||||
$model = new Model('', $this->getConfig());
|
$data = [
|
||||||
$data = $_POST = [
|
'username' => 'username',
|
||||||
'username' => 'username',
|
'nickname' => 'nickname',
|
||||||
'nickname' => 'nickname',
|
'password' => '123456',
|
||||||
'password' => '123456',
|
'repassword' => '123456',
|
||||||
'repassword' => '123456',
|
'email' => 'abc@abc.com',
|
||||||
'mobile' => '13800000000',
|
'sex' => '0',
|
||||||
'email' => 'abc@abc.com',
|
'age' => '20',
|
||||||
'sex' => '0',
|
'code' => '1234',
|
||||||
'age' => '20',
|
];
|
||||||
'code' => '1234',
|
|
||||||
];
|
|
||||||
|
|
||||||
$validate = [
|
$validate = [
|
||||||
'__pattern__' => [
|
['username', 'length:5,15', '用户名长度为5到15个字符'],
|
||||||
'mobile' => '/^1(?:[358]\d|7[6-8])\d{8}$/',
|
['nickname', 'require', '请填昵称'],
|
||||||
'require' => '/.+/',
|
['password', '[\w-]{6,15}', '密码长度为6到15个字符'],
|
||||||
],
|
['repassword', 'confirm:password', '两次密码不一到致'],
|
||||||
'__all__' => [
|
['email', 'filter:validate_email', '邮箱格式错误'],
|
||||||
'code' => function ($value, $data) {
|
['sex', 'in:0,1', '性别只能为为男或女'],
|
||||||
return '1234' != $value ? 'code error' : true;
|
['age', 'between:1,80', '年龄只能在10-80之间'],
|
||||||
},
|
];
|
||||||
],
|
$result = $model->validate($validate)->create($data);
|
||||||
'user' => [
|
$this->assertEmpty($model->getError());
|
||||||
['username', [ & $this, 'checkName'], '用户名长度为5到15个字符', 'callback', 'username'],
|
|
||||||
['username', function ($value, $data) {
|
|
||||||
return 'admin' == $value ? '此用户名已被使用' : true;
|
|
||||||
}],
|
|
||||||
'nickname' => ['require', '请填昵称'],
|
|
||||||
'password' => ['[\w-]{6,15}', '密码长度为6到15个字符'],
|
|
||||||
'repassword' => ['password', '两次密码不一到致', 'confirm'],
|
|
||||||
'mobile' => ['mobile', '手机号错误'],
|
|
||||||
'email' => ['validate_email', '邮箱格式错误', 'filter'],
|
|
||||||
'sex' => ['0,1', '性别只能为为男或女', 'in'],
|
|
||||||
'age' => ['1,80', '年龄只能在10-80之间', 'between'],
|
|
||||||
'__option__' => [
|
|
||||||
'scene' => [
|
|
||||||
'add' => 'username,nickname,password,repassword,mobile,email,age,code',
|
|
||||||
'edit' => 'nickname,password,repassword,mobile,email,sex,age,code',
|
|
||||||
],
|
|
||||||
'value_validate' => 'email',
|
|
||||||
'exists_validate' => 'password,repassword,code',
|
|
||||||
'patch' => true,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
Config::set('validate', $validate);
|
|
||||||
$result = $model->validate('user.add')->create();
|
|
||||||
$this->assertEmpty($model->getError());
|
|
||||||
|
|
||||||
unset($data['password'], $data['repassword']);
|
|
||||||
$data['email'] = '';
|
|
||||||
$result = $model->validate('user.edit')->create($data);
|
|
||||||
$this->assertEmpty($model->getError());
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function checkName($value, $field)
|
public function checkName($value, $field)
|
||||||
|
|||||||
@@ -47,39 +47,40 @@ class validateTest extends \PHPUnit_Framework_TestCase
|
|||||||
public function testRule()
|
public function testRule()
|
||||||
{
|
{
|
||||||
$rule = [
|
$rule = [
|
||||||
'name' => 'require|alphaNum|max:25',
|
'name' => 'require|alphaNum|max:25|expire:2016-1-1,2026-1-1',
|
||||||
'account' => 'alphaDash|min:4|length:4,30',
|
'account' => 'requireIf:name,thinkphp|alphaDash|min:4|length:4,30',
|
||||||
'age' => 'number|between:1,120',
|
'age' => 'number|between:1,120',
|
||||||
'email' => 'email',
|
'email' => 'requireWith:name|email',
|
||||||
'url' => 'activeUrl',
|
'host' => 'activeUrl',
|
||||||
|
'url' => 'url',
|
||||||
'ip' => 'ip',
|
'ip' => 'ip',
|
||||||
'score' => 'float|gt:60',
|
'score' => 'float|gt:60|notBetween:90,100|notIn:70,80|lt:100|elt:100|egt:60',
|
||||||
'status' => 'integer|in:0,1,2',
|
'status' => 'integer|in:0,1,2',
|
||||||
'begin_time' => 'after:2016-3-18',
|
'begin_time' => 'after:2016-3-18',
|
||||||
'end_time' => 'before:2016-10-01',
|
'end_time' => 'before:2016-10-01',
|
||||||
'info' => 'require|array',
|
'info' => 'require|array',
|
||||||
|
'info.name' => 'require|length:8|alpha|same:thinkphp',
|
||||||
'value' => 'same:100',
|
'value' => 'same:100',
|
||||||
'bool' => 'boolean',
|
'bool' => 'boolean',
|
||||||
|
|
||||||
];
|
];
|
||||||
$data = [
|
$data = [
|
||||||
'name' => 'thinkphp',
|
'name' => 'thinkphp',
|
||||||
'account' => 'liuchen',
|
'account' => 'liuchen',
|
||||||
'age' => 10,
|
'age' => 10,
|
||||||
'email' => 'thinkphp@qq.com',
|
'email' => 'thinkphp@qq.com',
|
||||||
'url' => 'thinkphp.cn',
|
'host' => 'thinkphp.cn',
|
||||||
|
'url' => 'http://thinkphp.cn/topic',
|
||||||
'ip' => '114.34.54.5',
|
'ip' => '114.34.54.5',
|
||||||
'score' => '89.15',
|
'score' => '89.15',
|
||||||
'status' => 1,
|
'status' => 1,
|
||||||
'begin_time' => '2016-3-20',
|
'begin_time' => '2016-3-20',
|
||||||
'end_time' => '2016-5-1',
|
'end_time' => '2016-5-1',
|
||||||
'info' => [1, 2, 3],
|
'info' => [1, 2, 3, 'name' => 'thinkphp'],
|
||||||
'zip' => '200000',
|
'zip' => '200000',
|
||||||
'date' => '16-3-8',
|
'date' => '16-3-8',
|
||||||
'ok' => 'yes',
|
'ok' => 'yes',
|
||||||
'value' => 100,
|
'value' => 100,
|
||||||
'bool' => 'true',
|
'bool' => 'true',
|
||||||
|
|
||||||
];
|
];
|
||||||
$validate = new Validate($rule);
|
$validate = new Validate($rule);
|
||||||
$validate->rule('zip', '/^\d{6}$/');
|
$validate->rule('zip', '/^\d{6}$/');
|
||||||
@@ -104,19 +105,6 @@ class validateTest extends \PHPUnit_Framework_TestCase
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testConfig()
|
|
||||||
{
|
|
||||||
$validate = new Validate();
|
|
||||||
$validate->config('value_validate', ['name', 'age', 'email']);
|
|
||||||
$validate->config([
|
|
||||||
'value_validate' => ['name', 'age', 'email'],
|
|
||||||
'exists_validate' => ['zip'],
|
|
||||||
'scene' => [
|
|
||||||
'edit' => ['name', 'age', 'email'],
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testMake()
|
public function testMake()
|
||||||
{
|
{
|
||||||
$rule = [
|
$rule = [
|
||||||
@@ -169,4 +157,25 @@ class validateTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(true, $result);
|
$this->assertEquals(true, $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testSetTypeMsg()
|
||||||
|
{
|
||||||
|
$rule = [
|
||||||
|
'name|名称' => 'require|max:25',
|
||||||
|
'age' => 'number|between:1,120',
|
||||||
|
'email' => 'email',
|
||||||
|
['sex', 'in:1,2', '性别错误'],
|
||||||
|
];
|
||||||
|
$data = [
|
||||||
|
'name' => '',
|
||||||
|
'age' => 10,
|
||||||
|
'email' => 'thinkphp@qq.com',
|
||||||
|
'sex' => '3',
|
||||||
|
];
|
||||||
|
$validate = new Validate($rule);
|
||||||
|
$validate->setTypeMsg('require', ':attribute必须');
|
||||||
|
$result = $validate->batch()->check($data);
|
||||||
|
$this->assertFalse($result);
|
||||||
|
$this->assertEquals(['name' => '名称必须', 'sex' => '性别错误'], $validate->getError());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user