mirror of
https://gitee.com/fastadminnet/framework.git
synced 2026-07-05 22:52:49 +08:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -28,6 +28,9 @@ class App
|
||||
*/
|
||||
public static function run()
|
||||
{
|
||||
// 加载环境变量配置文件
|
||||
Config::loadEnv(APP_PATH . 'env' . EXT);
|
||||
|
||||
// 初始化应用(公共模块)
|
||||
self::initModule(COMMON_MODULE, Config::get());
|
||||
|
||||
@@ -130,6 +133,7 @@ class App
|
||||
break;
|
||||
case 'PUT':
|
||||
parse_str(file_get_contents('php://input'), $vars);
|
||||
$vars = array_merge($_GET, $vars);
|
||||
break;
|
||||
default:
|
||||
$vars = $_GET;
|
||||
|
||||
@@ -29,7 +29,6 @@ class Config
|
||||
|
||||
/**
|
||||
* 解析配置文件或内容
|
||||
*
|
||||
* @param string $config 配置文件路径或内容
|
||||
* @param string $type 配置解析类型
|
||||
* @param string $range 作用域
|
||||
@@ -46,7 +45,6 @@ class Config
|
||||
|
||||
/**
|
||||
* 加载配置文件(PHP格式)
|
||||
*
|
||||
* @param string $file 配置文件名
|
||||
* @param string $name 配置名(如设置即表示二级配置)
|
||||
* @param string $range 作用域
|
||||
@@ -63,9 +61,28 @@ class Config
|
||||
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 $range 作用域
|
||||
* @return bool
|
||||
@@ -85,7 +102,6 @@ class Config
|
||||
|
||||
/**
|
||||
* 获取配置参数 为空则获取所有配置
|
||||
*
|
||||
* @param string $name 配置参数名(支持二级配置 .号分割)
|
||||
* @param string $range 作用域
|
||||
* @return mixed
|
||||
@@ -119,7 +135,6 @@ class Config
|
||||
|
||||
/**
|
||||
* 设置配置参数 name为数组则为批量设置
|
||||
*
|
||||
* @param string $name 配置参数名(支持二级配置 .号分割)
|
||||
* @param mixed $value 配置值
|
||||
* @param string $range 作用域
|
||||
|
||||
@@ -147,21 +147,33 @@ class Controller
|
||||
* @param array $data 数据
|
||||
* @param string|array $validate 验证器名或者验证规则数组
|
||||
* @param array $message 提示信息
|
||||
* @param mixed $callback 回调方法(闭包)
|
||||
* @return void
|
||||
*/
|
||||
public function validate($data, $validate, $message = [])
|
||||
public function validate($data, $validate, $message = [], $callback = null)
|
||||
{
|
||||
if (is_array($validate)) {
|
||||
$v = Loader::validate();
|
||||
$v = Loader::validate(Config::get('default_validate'));
|
||||
$v->rule($validate);
|
||||
} else {
|
||||
if (strpos($validate, '.')) {
|
||||
// 支持场景
|
||||
list($validate, $scene) = explode('.', $validate);
|
||||
}
|
||||
$v = Loader::validate($validate);
|
||||
if (!empty($scene)) {
|
||||
$v->scene($scene);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($message)) {
|
||||
$v->message($message);
|
||||
}
|
||||
|
||||
if (is_callable($callback)) {
|
||||
call_user_func_array($callback, [$v, &$data]);
|
||||
}
|
||||
|
||||
if (!$v->check($data)) {
|
||||
return $v->getError();
|
||||
} else {
|
||||
|
||||
@@ -54,8 +54,6 @@ class Model
|
||||
protected $scope = [];
|
||||
// 字段映射定义
|
||||
protected $map = [];
|
||||
// 字段验证规则定义
|
||||
protected $rule = [];
|
||||
|
||||
/**
|
||||
* 架构函数
|
||||
@@ -991,12 +989,18 @@ class Model
|
||||
if (!empty($this->options['validate'])) {
|
||||
$info = $this->options['validate'];
|
||||
if (is_array($info)) {
|
||||
$validate = Loader::validate();
|
||||
$validate = Loader::validate(Config::get('default_validate'));
|
||||
$validate->rule($info['rule']);
|
||||
$validate->message($info['msg']);
|
||||
} 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);
|
||||
if (!empty($scene)) {
|
||||
$validate->scene($scene);
|
||||
}
|
||||
}
|
||||
if (!$validate->check($data)) {
|
||||
$this->error = $validate->getError();
|
||||
@@ -1726,8 +1730,8 @@ class Model
|
||||
public function order($field, $order = null)
|
||||
{
|
||||
if (!empty($field)) {
|
||||
if (!is_array($field)) {
|
||||
$field = empty($order) ? [$field] : [(string) $field => (string) $order];
|
||||
if (is_string($field)) {
|
||||
$field = empty($order) ? $field : [$field => $order];
|
||||
}
|
||||
$this->options['order'] = $field;
|
||||
}
|
||||
|
||||
@@ -32,58 +32,52 @@ class Validate
|
||||
|
||||
// 验证规则默认提示信息
|
||||
protected $typeMsg = [
|
||||
'require' => '不能为空',
|
||||
'number' => '必须是数字',
|
||||
'float' => '必须是浮点数',
|
||||
'boolean' => '必须是布尔值',
|
||||
'email' => '格式不符',
|
||||
'array' => '必须是数组',
|
||||
'accepted' => '必须是yes、on或者1',
|
||||
'date' => '格式不符合',
|
||||
'alpha' => '只能是字母',
|
||||
'alphaNum' => '只能是字母和数字',
|
||||
'alphaDash' => '只能是字母、数字和下划线_及破折号-',
|
||||
'activeUrl' => '不是有效的域名或者IP',
|
||||
'url' => '不是有效的URL地址',
|
||||
'ip' => '不是有效的IP地址',
|
||||
'dateFormat' => '必须使用日期格式 :rule',
|
||||
'in' => '必须在 :rule 范围内',
|
||||
'notIn' => '不能在 :rule 范围内',
|
||||
'between' => '只能在 :1 - :2 之间',
|
||||
'notBetween' => '不能在 :1 - :2 之间',
|
||||
'length' => '长度不符合要求 :rule',
|
||||
'max' => '长度不能超过 :rule',
|
||||
'min' => '长度不能小于 :rule',
|
||||
'after' => '日期不能小于 :rule',
|
||||
'before' => '日期不能超过 :rule',
|
||||
'require' => ':attribute不能为空',
|
||||
'number' => ':attribute必须是数字',
|
||||
'float' => ':attribute必须是浮点数',
|
||||
'boolean' => ':attribute必须是布尔值',
|
||||
'email' => ':attribute格式不符',
|
||||
'array' => ':attribute必须是数组',
|
||||
'accepted' => ':attribute必须是yes、on或者1',
|
||||
'date' => ':attribute格式不符合',
|
||||
'alpha' => ':attribute只能是字母',
|
||||
'alphaNum' => ':attribute只能是字母和数字',
|
||||
'alphaDash' => ':attribute只能是字母、数字和下划线_及破折号-',
|
||||
'activeUrl' => ':attribute不是有效的域名或者IP',
|
||||
'url' => ':attribute不是有效的URL地址',
|
||||
'ip' => ':attribute不是有效的IP地址',
|
||||
'dateFormat' => ':attribute必须使用日期格式 :rule',
|
||||
'in' => ':attribute必须在 :rule 范围内',
|
||||
'notIn' => ':attribute不能在 :rule 范围内',
|
||||
'between' => ':attribute只能在 :1 - :2 之间',
|
||||
'notBetween' => ':attribute不能在 :1 - :2 之间',
|
||||
'length' => ':attribute长度不符合要求 :rule',
|
||||
'max' => ':attribute长度不能超过 :rule',
|
||||
'min' => ':attribute长度不能小于 :rule',
|
||||
'after' => ':attribute日期不能小于 :rule',
|
||||
'before' => ':attribute日期不能超过 :rule',
|
||||
'expire' => '不在有效期内 :rule',
|
||||
'allowIp' => '不允许的IP访问',
|
||||
'denyIp' => '禁止的IP访问',
|
||||
'confirm' => '和字段 :rule 不一致',
|
||||
'egt' => '必须大于等于 :rule',
|
||||
'gt' => '必须大于 :rule',
|
||||
'elt' => '必须小于等于 :rule',
|
||||
'lt' => '必须小于 :rule',
|
||||
'eq' => '必须等于 :rule',
|
||||
'unique' => '已存在',
|
||||
'regex' => '不符合指定规则',
|
||||
'confirm' => ':attribute和字段 :rule 不一致',
|
||||
'egt' => ':attribute必须大于等于 :rule',
|
||||
'gt' => ':attribute必须大于 :rule',
|
||||
'elt' => ':attribute必须小于等于 :rule',
|
||||
'lt' => ':attribute必须小于 :rule',
|
||||
'eq' => ':attribute必须等于 :rule',
|
||||
'unique' => ':attribute已存在',
|
||||
'regex' => ':attribute不符合指定规则',
|
||||
];
|
||||
|
||||
// 当前验证场景
|
||||
protected $scene = null;
|
||||
protected $currentScene = null;
|
||||
|
||||
// 正则表达式 regex = ['zip'=>'\d{6}',...]
|
||||
protected $regex = [];
|
||||
|
||||
// 验证参数
|
||||
protected $config = [
|
||||
// 有值才验证 value_validate = [name1,name2,...]
|
||||
'value_validate' => [],
|
||||
// 存在就验证 exists_validate = [name1,name2,...]
|
||||
'exists_validate' => [],
|
||||
// 验证场景 scene = ['edit'=>'name1,name2,...']
|
||||
'scene' => [],
|
||||
];
|
||||
// 验证场景 scene = ['edit'=>'name1,name2,...']
|
||||
protected $scene = [];
|
||||
|
||||
// 验证失败错误信息
|
||||
protected $error = [];
|
||||
|
||||
@@ -95,19 +89,11 @@ class Validate
|
||||
* @access public
|
||||
* @param array $rules 验证规则
|
||||
* @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->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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 传入验证参数
|
||||
* @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
|
||||
* @param string $name 场景名
|
||||
* @param string|array $name 场景名或者场景设置数组
|
||||
* @param mixed $fields 要验证的字段
|
||||
* @return Validate
|
||||
*/
|
||||
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 {
|
||||
// 设置验证场景
|
||||
$this->config['scene'][$name] = $fields;
|
||||
$this->scene[$name] = $fields;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
@@ -261,34 +232,43 @@ class Validate
|
||||
|
||||
// 分析验证规则
|
||||
$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, '|')) {
|
||||
// 支持 字段|描述 用于返回默认错误
|
||||
// 字段|描述 用于指定属性名称
|
||||
list($key, $title) = explode('|', $key);
|
||||
} else {
|
||||
$title = $key;
|
||||
}
|
||||
|
||||
// 场景检测
|
||||
if (!empty($scene) && !in_array($key, $scene)) {
|
||||
continue;
|
||||
if (!empty($scene)) {
|
||||
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);
|
||||
|
||||
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))) {
|
||||
// 不满足自动验证条件
|
||||
continue;
|
||||
}
|
||||
|
||||
// 验证字段规则
|
||||
$result = $this->checkItem($key, $value, $rule, $data, $title);
|
||||
// 字段验证
|
||||
$result = $this->checkItem($key, $value, $rule, $data, $title, $msg);
|
||||
|
||||
if (true !== $result) {
|
||||
// 没有返回true 则表示验证失败
|
||||
@@ -316,9 +296,10 @@ class Validate
|
||||
* @param mixed $rules 验证规则
|
||||
* @param array $data 数据
|
||||
* @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) {
|
||||
// 匿名函数验证 支持传入当前字段和所有字段两个数据
|
||||
@@ -328,7 +309,7 @@ class Validate
|
||||
if (is_string($rules)) {
|
||||
$rules = explode('|', $rules);
|
||||
}
|
||||
$error = [];
|
||||
$i = 0;
|
||||
foreach ($rules as $key => $rule) {
|
||||
if ($rule instanceof \Closure) {
|
||||
$result = call_user_func_array($rule, [$value, &$data]);
|
||||
@@ -347,34 +328,34 @@ class Validate
|
||||
} else {
|
||||
$info = $type = $key;
|
||||
}
|
||||
// 验证类型
|
||||
$callback = isset($this->type[$type]) ? $this->type[$type] : [$this, $type];
|
||||
// 验证数据
|
||||
$result = call_user_func_array($callback, [$value, $rule, &$data, $field]);
|
||||
|
||||
// 如果不是require 有数据才会行验证
|
||||
if (0 === strpos($info, 'require') || !empty($value)) {
|
||||
// 验证类型
|
||||
$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 (isset($this->message[$field . '.' . $info])) {
|
||||
$error[] = $this->message[$field . '.' . $info];
|
||||
} elseif (isset($this->message[$field . '.'])) {
|
||||
$error[] = $this->message[$field . '.'];
|
||||
if (isset($msg[$i])) {
|
||||
$message = $msg[$i];
|
||||
} else {
|
||||
$error[] = $this->getTypeMsg($title ?: $field, $info, $rule);
|
||||
$message = $this->getRuleMsg($field, $title, $info, $rule);
|
||||
}
|
||||
} elseif (is_string($result)) {
|
||||
$error[] = $result;
|
||||
} elseif (is_array($result)) {
|
||||
// 自定义错误信息数组
|
||||
return $message;
|
||||
} elseif (true !== $result) {
|
||||
// 返回自定义错误信息
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
if (!empty($error)) {
|
||||
$result = implode(',', $error);
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
// 验证失败返回错误信息
|
||||
return $result;
|
||||
return true !== $result ? $result : true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -541,26 +522,38 @@ class Validate
|
||||
* 验证是否唯一
|
||||
* @access protected
|
||||
* @param mixed $value 字段值
|
||||
* @param mixed $rule 验证规则 格式:数据表,字段名,排除ID
|
||||
* @param mixed $rule 验证规则 格式:数据表,字段名,排除ID,主键名
|
||||
* @param array $data 数据
|
||||
* @param string $field 验证字段名
|
||||
* @return bool
|
||||
*/
|
||||
protected function unique($value, $rule, $data, $field)
|
||||
{
|
||||
$rule = explode(',', $rule);
|
||||
if (is_string($rule)) {
|
||||
$rule = explode(',', $rule);
|
||||
}
|
||||
$model = Loader::table($rule[0]);
|
||||
$key = isset($rule[3]) ? $rule[3] : $model->getPk();
|
||||
$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])) {
|
||||
$except = $rule[2];
|
||||
$map[$key] = ['neq', $rule[2]];
|
||||
} elseif (isset($data[$key])) {
|
||||
$except = $data[$key];
|
||||
}
|
||||
$map[$field] = $value;
|
||||
if (isset($except)) {
|
||||
$map[$key] = ['neq', $except];
|
||||
$map[$key] = ['neq', $data[$key]];
|
||||
}
|
||||
|
||||
if ($model->where($map)->field($key)->find()) {
|
||||
return false;
|
||||
}
|
||||
@@ -589,18 +582,18 @@ class Validate
|
||||
*/
|
||||
protected function filter($value, $rule)
|
||||
{
|
||||
if (is_int($rule)) {
|
||||
$param = null;
|
||||
} elseif (is_string($rule) && strpos($rule, ',')) {
|
||||
if (is_string($rule) && strpos($rule, ',')) {
|
||||
list($rule, $param) = explode(',', $rule);
|
||||
} elseif (is_array($rule)) {
|
||||
$param = isset($rule[1]) ? $rule[1] : null;
|
||||
} else {
|
||||
$param = null;
|
||||
}
|
||||
return false !== filter_var($value, is_int($rule) ? $rule : filter_id($rule), $param);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证某个字段的值等于某个值的时候必须
|
||||
* 验证某个字段等于某个值的时候必须
|
||||
* @access protected
|
||||
* @param mixed $value 字段值
|
||||
* @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
|
||||
@@ -835,28 +846,39 @@ class Validate
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证规则的默认提示信息
|
||||
* 获取验证规则的错误提示信息
|
||||
* @access protected
|
||||
* @param string $attribute 字段名称
|
||||
* @param string $type 验证类型名称
|
||||
* @param mixed $rule 验证规则
|
||||
* @param string $attribute 字段英文名
|
||||
* @param string $title 字段描述名
|
||||
* @param string $type 验证规则名称
|
||||
* @param mixed $rule 验证规则数据
|
||||
* @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, ',')) {
|
||||
$array = array_pad(explode(',', $rule), 3, '');
|
||||
} else {
|
||||
$array = array_pad([], 3, '');
|
||||
}
|
||||
return (false === strpos($this->typeMsg[$type], ':attribute') ? $attribute : '') . str_replace(
|
||||
[':rule', ':attribute', ':1', ':2', ':3'],
|
||||
[(string) $rule, $attribute, $array[0], $array[1], $array[2]],
|
||||
$this->typeMsg[$type]);
|
||||
} else {
|
||||
return $attribute . '规则错误';
|
||||
$msg = str_replace(
|
||||
[':attribute', ':rule', ':1', ':2', ':3'],
|
||||
[$title, (string) $rule, $array[0], $array[1], $array[2]],
|
||||
$msg);
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -869,12 +891,12 @@ class Validate
|
||||
{
|
||||
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)) {
|
||||
$scene = explode(',', $scene);
|
||||
}
|
||||
|
||||
@@ -53,8 +53,9 @@ class File
|
||||
} else {
|
||||
$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);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||
|
||||
@@ -41,8 +41,9 @@ class Sae
|
||||
} else {
|
||||
$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);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$time_str = " [运行时间:{$runtime}s] [吞吐率:{$reqs}req/s]";
|
||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||
|
||||
@@ -59,8 +59,9 @@ class Socket
|
||||
if (!$this->check()) {
|
||||
return false;
|
||||
}
|
||||
$runtime = number_format(microtime(true) - START_TIME, 6);
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$reqs = number_format(1 / $runtime, 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$time_str = " [运行时间:{$runtime}s][吞吐率:{$reqs}req/s]";
|
||||
$memory_use = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
$memory_str = " [内存消耗:{$memory_use}kb]";
|
||||
|
||||
@@ -43,8 +43,9 @@ class Trace
|
||||
return false;
|
||||
}
|
||||
// 获取基本信息
|
||||
$runtime = number_format(microtime(true) - START_TIME, 6);
|
||||
$runtime = microtime(true) - START_TIME;
|
||||
$reqs = number_format(1 / $runtime, 2);
|
||||
$runtime = number_format($runtime, 6);
|
||||
$mem = number_format((memory_get_usage() - START_MEM) / 1024, 2);
|
||||
|
||||
// 页面Trace信息
|
||||
|
||||
@@ -31,28 +31,31 @@ trait View
|
||||
{
|
||||
if (empty($this->trueTableName)) {
|
||||
$tableName = '';
|
||||
foreach ($this->viewFields as $key => $view) {
|
||||
$len = 0;
|
||||
foreach ($this->viewFields as $name => $view) {
|
||||
// 获取数据表名称
|
||||
if (isset($view['_table'])) {
|
||||
// 2011/10/17 添加实际表名定义支持 可以实现同一个表的视图
|
||||
$tableName .= $view['_table'];
|
||||
} else {
|
||||
$class = $key . 'Model';
|
||||
$model = class_exists($class) ? new $class() : M($key);
|
||||
$tableName .= $model->getTableName();
|
||||
$tableName .= \think\Loader::model($name)->getTableName();
|
||||
}
|
||||
// 表别名定义
|
||||
$tableName .= !empty($view['_as']) ? ' ' . $view['_as'] : ' ' . $key;
|
||||
$tableName .= !empty($view['_as']) ? ' ' . $view['_as'] : ' ' . $name;
|
||||
// 支持ON 条件定义
|
||||
$tableName .= !empty($view['_on']) ? ' ON ' . $view['_on'] : '';
|
||||
// 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
|
||||
$type = !empty($view['_type']) ? $view['_type'] : '';
|
||||
$tableName .= ' ' . strtoupper($type) . ' JOIN ';
|
||||
$len = strlen($type . '_JOIN ');
|
||||
if (!empty($view['_type'])) {
|
||||
// 指定JOIN类型 例如 RIGHT INNER LEFT 下一个表有效
|
||||
$type = strtoupper($view['_type']);
|
||||
$tableName .= ' ' . $type . ' JOIN ';
|
||||
if ($view == end($this->viewFields)) {
|
||||
$len = strlen($type) + 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
$tableName = substr($tableName, 0, -$len);
|
||||
$this->trueTableName = $tableName;
|
||||
$this->trueTableName = $len ? substr($tableName, 0, -$len) : $tableName;
|
||||
}
|
||||
|
||||
return $this->trueTableName;
|
||||
}
|
||||
|
||||
@@ -64,26 +67,43 @@ trait View
|
||||
*/
|
||||
protected function _options_filter(&$options)
|
||||
{
|
||||
if (isset($options['field'])) {
|
||||
$options['field'] = $this->checkFields($options['field']);
|
||||
} else {
|
||||
$options['field'] = $this->checkFields();
|
||||
$viewFields = [];
|
||||
foreach ($this->viewFields as $name => $val) {
|
||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
||||
$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'])) {
|
||||
$options['group'] = $this->checkGroup($options['group']);
|
||||
$options['group'] = $this->checkGroup($options['group'], $viewFields);
|
||||
}
|
||||
if (isset($options['where'])) {
|
||||
$options['where'] = $this->checkCondition($options['where']);
|
||||
$options['where'] = $this->checkCondition($options['where'], $viewFields);
|
||||
}
|
||||
if (isset($options['order'])) {
|
||||
$options['order'] = $this->checkOrder($options['order']);
|
||||
$options['order'] = $this->checkOrder($options['order'], $viewFields);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否定义了所有字段
|
||||
* @access protected
|
||||
* @param string $name 模型名称
|
||||
* @param string $name 模型名称
|
||||
* @param array $fields 字段数组
|
||||
* @return array
|
||||
*/
|
||||
@@ -94,161 +114,143 @@ trait View
|
||||
$fields = array_merge($fields, \think\Loader::model($name)->getFields());
|
||||
unset($fields[$pos]);
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查条件中的视图字段
|
||||
* @access protected
|
||||
* @param mixed $data 条件表达式
|
||||
* @param mixed $data 条件表达式
|
||||
* @param array $fields 视图字段数组
|
||||
* @return array
|
||||
*/
|
||||
protected function checkCondition($where)
|
||||
protected function checkCondition($where, $viewFields)
|
||||
{
|
||||
if (is_array($where)) {
|
||||
$view = [];
|
||||
// 检查视图字段
|
||||
foreach ($this->viewFields as $key => $val) {
|
||||
$k = isset($val['_as']) ? $val['_as'] : $key;
|
||||
$val = $this->_checkFields($key, $val);
|
||||
foreach ($where as $name => $value) {
|
||||
if (false !== $field = array_search($name, $val, true)) {
|
||||
// 存在视图字段
|
||||
$_key = is_numeric($field) ? $k . '.' . $name : $k . '.' . $field;
|
||||
$view[$_key] = $value;
|
||||
unset($where[$name]);
|
||||
}
|
||||
$_where = [];
|
||||
foreach ($where as $field => $value) {
|
||||
if (false !== $k = array_search($field, $viewFields, true)) {
|
||||
// 存在视图字段
|
||||
$_where[$k] = $value;
|
||||
} else {
|
||||
$_where[$field] = $value;
|
||||
}
|
||||
}
|
||||
$where = array_merge($where, $view);
|
||||
return $_where;
|
||||
} else {
|
||||
return $where;
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查Order表达式中的视图字段
|
||||
* @access protected
|
||||
* @param string $order 字段
|
||||
* @param string|array $order 字段
|
||||
* @param array $fields 视图字段数组
|
||||
* @return string
|
||||
*/
|
||||
protected function checkOrder($order = '')
|
||||
protected function checkOrder($order = '', $viewFields)
|
||||
{
|
||||
if (is_string($order) && !empty($order)) {
|
||||
$orders = explode(',', $order);
|
||||
$_order = [];
|
||||
foreach ($orders as $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);
|
||||
if (empty($order)) {
|
||||
return '';
|
||||
} elseif (is_string($order)) {
|
||||
$order = explode(',', $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表达式中的视图字段
|
||||
* @access protected
|
||||
* @param string $group 字段
|
||||
* @param array $fields 视图字段数组
|
||||
* @return string
|
||||
*/
|
||||
protected function checkGroup($group = '')
|
||||
protected function checkGroup($group = '', $viewFields)
|
||||
{
|
||||
if (!empty($group)) {
|
||||
$groups = explode(',', $group);
|
||||
$_group = [];
|
||||
foreach ($groups as $field) {
|
||||
// 解析成视图字段
|
||||
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);
|
||||
if (empty($group)) {
|
||||
return '';
|
||||
} elseif (is_string($group)) {
|
||||
$group = explode(',', $group);
|
||||
}
|
||||
return $group;
|
||||
foreach ($group as &$field) {
|
||||
if (false !== $k = array_search($field, $viewFields, true)) {
|
||||
// 存在视图字段
|
||||
$field = $k;
|
||||
}
|
||||
}
|
||||
|
||||
return implode(',', $group);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查fields表达式中的视图字段
|
||||
* @access protected
|
||||
* @param string $fields 字段
|
||||
* @param array $fields 视图字段数组
|
||||
* @return string
|
||||
*/
|
||||
protected function checkFields($fields = '')
|
||||
protected function checkFields($fields = '*', $viewFields)
|
||||
{
|
||||
if (empty($fields) || '*' == $fields) {
|
||||
// 获取全部视图字段
|
||||
$fields = [];
|
||||
foreach ($this->viewFields as $name => $val) {
|
||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
||||
$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)) {
|
||||
var_dump($fields);
|
||||
if (is_string($fields)) {
|
||||
if ('*' == $fields) {
|
||||
return $viewFields;
|
||||
} else {
|
||||
$fields = explode(',', $fields);
|
||||
}
|
||||
// 解析成视图字段
|
||||
$array = [];
|
||||
foreach ($fields as $key => $field) {
|
||||
if (strpos($field, '(') || strpos(strtolower($field), ' as ')) {
|
||||
// 使用了函数或者别名
|
||||
$array[] = $field;
|
||||
unset($fields[$key]);
|
||||
}
|
||||
$_fields = [];
|
||||
foreach ($fields as $key => $field) {
|
||||
if (is_numeric($key)) {
|
||||
if ($pos = strpos($field, ' ')) {
|
||||
$alias = substr($field, $pos);
|
||||
$field = substr($field, 0, $pos);
|
||||
} else {
|
||||
$alias = ' AS ' . $field;
|
||||
}
|
||||
} else {
|
||||
$alias = ' AS ' . $field;
|
||||
$field = $key;
|
||||
}
|
||||
foreach ($this->viewFields as $name => $val) {
|
||||
$k = isset($val['_as']) ? $val['_as'] : $name;
|
||||
$val = $this->_checkFields($name, $val);
|
||||
foreach ($fields as $key => $field) {
|
||||
if (false !== $_field = array_search($field, $val, true)) {
|
||||
// 存在视图字段
|
||||
if (is_numeric($_field)) {
|
||||
$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;
|
||||
}
|
||||
if (strpos($field, '(')) {
|
||||
if (preg_match_all('/(?<!\s)\b(\w+)\b(?![\.\(])/', $field, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
// 倒序找出的字段数组,以便从后向前替换
|
||||
$items = array_reverse($matches[0]);
|
||||
foreach ($items as $item) {
|
||||
if (false !== $k = array_search($item[0], $viewFields, true)) {
|
||||
$field = substr_replace($field, $k, $item[1], strlen($item[0]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif (false !== $k = array_search($field, $viewFields, true)) {
|
||||
// 存在视图字段
|
||||
$field = $k . $alias;
|
||||
}
|
||||
$fields = implode(',', $array);
|
||||
$_fields[] = $field;
|
||||
}
|
||||
return $fields;
|
||||
|
||||
return $_fields;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user