Merge remote-tracking branch 'origin/master'

This commit is contained in:
yunwuxin
2016-03-23 14:46:55 +08:00
18 changed files with 483 additions and 359 deletions

View File

@@ -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;

View File

@@ -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 作用域

View File

@@ -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 {

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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]";

View File

@@ -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]";

View File

@@ -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]";

View File

@@ -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信息

View File

@@ -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;
}
}