From d19ca3fb6fa3a22e194587fbe1e23c8023219f69 Mon Sep 17 00:00:00 2001 From: zhaoxiang Date: Tue, 11 Dec 2018 18:27:44 +0800 Subject: [PATCH] =?UTF-8?q?modified=20=E5=8D=87=E7=BA=A7ThinkPHP=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E8=87=B35.0.23?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- thinkphp/.gitignore | 0 thinkphp/.htaccess | 0 thinkphp/.travis.yml | 0 thinkphp/base.php | 2 +- thinkphp/lang/zh-cn.php | 1 + thinkphp/library/think/App.php | 5 + thinkphp/library/think/Log.php | 4 +- thinkphp/library/think/Model.php | 44 ++- thinkphp/library/think/Request.php | 195 ++++++----- thinkphp/library/think/Route.php | 305 ++++++++++-------- thinkphp/library/think/Url.php | 2 +- thinkphp/library/think/Validate.php | 36 ++- .../library/think/cache/driver/Memcache.php | 2 +- thinkphp/library/think/cache/driver/Redis.php | 2 +- .../library/think/console/command/Clear.php | 13 +- thinkphp/library/think/db/Builder.php | 16 +- thinkphp/library/think/db/Connection.php | 27 +- thinkphp/library/think/db/Query.php | 69 +++- thinkphp/library/think/db/builder/Mysql.php | 3 + thinkphp/library/think/db/builder/Sqlsrv.php | 4 + .../library/think/db/connector/Sqlsrv.php | 5 +- thinkphp/library/think/log/driver/File.php | 268 ++++++++++----- thinkphp/library/think/log/driver/Socket.php | 2 +- .../think/model/relation/BelongsToMany.php | 73 ++++- .../library/think/model/relation/HasMany.php | 24 +- .../think/model/relation/HasManyThrough.php | 12 + .../think/model/relation/MorphMany.php | 27 +- .../library/think/model/relation/MorphOne.php | 30 +- .../library/think/model/relation/MorphTo.php | 13 +- .../library/think/model/relation/OneToOne.php | 11 + thinkphp/library/traits/model/SoftDelete.php | 3 +- 31 files changed, 825 insertions(+), 373 deletions(-) mode change 100644 => 100755 thinkphp/.gitignore mode change 100644 => 100755 thinkphp/.htaccess mode change 100644 => 100755 thinkphp/.travis.yml diff --git a/thinkphp/.gitignore b/thinkphp/.gitignore old mode 100644 new mode 100755 diff --git a/thinkphp/.htaccess b/thinkphp/.htaccess old mode 100644 new mode 100755 diff --git a/thinkphp/.travis.yml b/thinkphp/.travis.yml old mode 100644 new mode 100755 diff --git a/thinkphp/base.php b/thinkphp/base.php index 87e1cc9..86c585b 100755 --- a/thinkphp/base.php +++ b/thinkphp/base.php @@ -9,7 +9,7 @@ // | Author: liu21st // +---------------------------------------------------------------------- -define('THINK_VERSION', '5.0.19'); +define('THINK_VERSION', '5.0.23'); define('THINK_START_TIME', microtime(true)); define('THINK_START_MEM', memory_get_usage()); define('EXT', '.php'); diff --git a/thinkphp/lang/zh-cn.php b/thinkphp/lang/zh-cn.php index c821f9f..eb7a914 100755 --- a/thinkphp/lang/zh-cn.php +++ b/thinkphp/lang/zh-cn.php @@ -48,6 +48,7 @@ return [ 'KVDB init error' => '没有初始化KVDB,请在SAE管理平台初始化KVDB服务', 'fields not exists' => '数据表字段不存在', 'where express error' => '查询表达式错误', + 'not support data' => '不支持的数据表达式', 'no data to update' => '没有任何数据需要更新', 'miss data to insert' => '缺少需要写入的数据', 'miss complex primary data' => '缺少复合主键数据', diff --git a/thinkphp/library/think/App.php b/thinkphp/library/think/App.php index 3c5f81f..f572b90 100755 --- a/thinkphp/library/think/App.php +++ b/thinkphp/library/think/App.php @@ -551,6 +551,11 @@ class App // 获取控制器名 $controller = strip_tags($result[1] ?: $config['default_controller']); + + if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) { + throw new HttpException(404, 'controller not exists:' . $controller); + } + $controller = $convert ? strtolower($controller) : $controller; // 获取操作名 diff --git a/thinkphp/library/think/Log.php b/thinkphp/library/think/Log.php index bf6c04f..c064306 100755 --- a/thinkphp/library/think/Log.php +++ b/thinkphp/library/think/Log.php @@ -176,7 +176,7 @@ class Log } } - if ($result = self::$driver->save($log)) { + if ($result = self::$driver->save($log, true)) { self::$log = []; } @@ -211,7 +211,7 @@ class Log is_null(self::$driver) && self::init(Config::get('log')); // 写入日志 - if ($result = self::$driver->save($log)) { + if ($result = self::$driver->save($log, false)) { self::$log = []; } diff --git a/thinkphp/library/think/Model.php b/thinkphp/library/think/Model.php index 386660c..2190e34 100755 --- a/thinkphp/library/think/Model.php +++ b/thinkphp/library/think/Model.php @@ -94,6 +94,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess protected $type = []; // 是否为更新数据 protected $isUpdate = false; + // 是否使用Replace + protected $replace = false; // 是否强制更新所有数据 protected $force = false; // 更新条件 @@ -1013,6 +1015,18 @@ abstract class Model implements \JsonSerializable, \ArrayAccess return false; } + /** + * 新增数据是否使用Replace + * @access public + * @param bool $replace + * @return $this + */ + public function replace($replace = true) + { + $this->replace = $replace; + return $this; + } + /** * 保存当前数据对象 * @access public @@ -1028,19 +1042,19 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $data = []; } - if (!empty($data)) { - // 数据自动验证 - if (!$this->validateData($data)) { - return false; - } - // 数据对象赋值 - foreach ($data as $key => $value) { - $this->setAttr($key, $value, $data); - } - if (!empty($where)) { - $this->isUpdate = true; - $this->updateWhere = $where; - } + // 数据自动验证 + if (!$this->validateData($data)) { + return false; + } + + // 数据对象赋值 + foreach ($data as $key => $value) { + $this->setAttr($key, $value, $data); + } + + if (!empty($where)) { + $this->isUpdate = true; + $this->updateWhere = $where; } // 自动关联写入 @@ -1163,9 +1177,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 检测字段 $allowFields = $this->checkAllowField(array_merge($this->auto, $this->insert)); if (!empty($allowFields)) { - $result = $this->getQuery()->strict(false)->field($allowFields)->insert($this->data, false, false, $sequence); + $result = $this->getQuery()->strict(false)->field($allowFields)->insert($this->data, $this->replace, false, $sequence); } else { - $result = $this->getQuery()->insert($this->data, false, false, $sequence); + $result = $this->getQuery()->insert($this->data, $this->replace, false, $sequence); } // 获取自动增长主键 diff --git a/thinkphp/library/think/Request.php b/thinkphp/library/think/Request.php index 7c72587..ac0c177 100755 --- a/thinkphp/library/think/Request.php +++ b/thinkphp/library/think/Request.php @@ -121,6 +121,11 @@ class Request protected $cache; // 缓存是否检查 protected $isCheckCache; + /** + * 是否合并Param + * @var bool + */ + protected $mergeParam = false; /** * 构造函数 @@ -155,8 +160,8 @@ class Request /** * Hook 方法注入 * @access public - * @param string|array $method 方法名 - * @param mixed $callback callable + * @param string|array $method 方法名 + * @param mixed $callback callable * @return void */ public static function hook($method, $callback = null) @@ -182,16 +187,28 @@ class Request return self::$instance; } + /** + * 销毁当前请求对象 + * @access public + * @return void + */ + public static function destroy() + { + if (!is_null(self::$instance)) { + self::$instance = null; + } + } + /** * 创建一个URL请求 * @access public - * @param string $uri URL地址 - * @param string $method 请求类型 - * @param array $params 请求参数 - * @param array $cookie - * @param array $files - * @param array $server - * @param string $content + * @param string $uri URL地址 + * @param string $method 请求类型 + * @param array $params 请求参数 + * @param array $cookie + * @param array $files + * @param array $server + * @param string $content * @return \think\Request */ public static function create($uri, $method = 'GET', $params = [], $cookie = [], $files = [], $server = [], $content = null) @@ -398,7 +415,7 @@ class Request foreach (Config::get('pathinfo_fetch') as $type) { if (!empty($_SERVER[$type])) { $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ? - substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; + substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; break; } } @@ -479,8 +496,8 @@ class Request /** * 设置资源类型 * @access public - * @param string|array $type 资源类型名 - * @param string $val 资源类型 + * @param string|array $type 资源类型名 + * @param string $val 资源类型 * @return void */ public function mimeType($type, $val = '') @@ -495,14 +512,14 @@ class Request /** * 当前的请求类型 * @access public - * @param bool $method true 获取原始请求类型 + * @param bool $method true 获取原始请求类型 * @return string */ public function method($method = false) { if (true === $method) { // 获取原始请求类型 - return IS_CLI ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']); + return $this->server('REQUEST_METHOD') ?: 'GET'; } elseif (!$this->method) { if (isset($_POST[Config::get('var_method')])) { $this->method = strtoupper($_POST[Config::get('var_method')]); @@ -510,7 +527,7 @@ class Request } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); } else { - $this->method = IS_CLI ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']); + $this->method = $this->server('REQUEST_METHOD') ?: 'GET'; } } return $this->method; @@ -609,14 +626,14 @@ class Request /** * 获取当前请求的参数 * @access public - * @param string|array $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function param($name = '', $default = null, $filter = '') { - if (empty($this->param)) { + if (empty($this->mergeParam)) { $method = $this->method(true); // 自动获取请求变量 switch ($method) { @@ -632,7 +649,8 @@ class Request $vars = []; } // 当前请求参数和URL地址中的参数合并 - $this->param = array_merge($this->get(false), $vars, $this->route(false)); + $this->param = array_merge($this->param, $this->get(false), $vars, $this->route(false)); + $this->mergeParam = true; } if (true === $name) { // 获取包含文件上传信息的数组 @@ -646,15 +664,16 @@ class Request /** * 设置获取路由参数 * @access public - * @param string|array $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function route($name = '', $default = null, $filter = '') { if (is_array($name)) { - $this->param = []; + $this->param = []; + $this->mergeParam = false; return $this->route = array_merge($this->route, $name); } return $this->input($this->route, $name, $default, $filter); @@ -663,9 +682,9 @@ class Request /** * 设置获取GET参数 * @access public - * @param string|array $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function get($name = '', $default = null, $filter = '') @@ -675,6 +694,7 @@ class Request } if (is_array($name)) { $this->param = []; + $this->mergeParam = false; return $this->get = array_merge($this->get, $name); } return $this->input($this->get, $name, $default, $filter); @@ -683,9 +703,9 @@ class Request /** * 设置获取POST参数 * @access public - * @param string $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function post($name = '', $default = null, $filter = '') @@ -699,7 +719,8 @@ class Request } } if (is_array($name)) { - $this->param = []; + $this->param = []; + $this->mergeParam = false; return $this->post = array_merge($this->post, $name); } return $this->input($this->post, $name, $default, $filter); @@ -708,9 +729,9 @@ class Request /** * 设置获取PUT参数 * @access public - * @param string|array $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function put($name = '', $default = null, $filter = '') @@ -725,6 +746,7 @@ class Request } if (is_array($name)) { $this->param = []; + $this->mergeParam = false; return $this->put = is_null($this->put) ? $name : array_merge($this->put, $name); } @@ -734,9 +756,9 @@ class Request /** * 设置获取DELETE参数 * @access public - * @param string|array $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function delete($name = '', $default = null, $filter = '') @@ -747,9 +769,9 @@ class Request /** * 设置获取PATCH参数 * @access public - * @param string|array $name 变量名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 变量名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function patch($name = '', $default = null, $filter = '') @@ -759,9 +781,9 @@ class Request /** * 获取request变量 - * @param string $name 数据名称 - * @param string $default 默认值 - * @param string|array $filter 过滤方法 + * @param string $name 数据名称 + * @param string $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function request($name = '', $default = null, $filter = '') @@ -770,7 +792,8 @@ class Request $this->request = $_REQUEST; } if (is_array($name)) { - $this->param = []; + $this->param = []; + $this->mergeParam = false; return $this->request = array_merge($this->request, $name); } return $this->input($this->request, $name, $default, $filter); @@ -779,9 +802,9 @@ class Request /** * 获取session数据 * @access public - * @param string|array $name 数据名称 - * @param string $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 数据名称 + * @param string $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function session($name = '', $default = null, $filter = '') @@ -798,9 +821,9 @@ class Request /** * 获取cookie参数 * @access public - * @param string|array $name 数据名称 - * @param string $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 数据名称 + * @param string $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function cookie($name = '', $default = null, $filter = '') @@ -831,9 +854,9 @@ class Request /** * 获取server参数 * @access public - * @param string|array $name 数据名称 - * @param string $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 数据名称 + * @param string $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function server($name = '', $default = null, $filter = '') @@ -909,9 +932,9 @@ class Request /** * 获取环境变量 - * @param string|array $name 数据名称 - * @param string $default 默认值 - * @param string|array $filter 过滤方法 + * @param string|array $name 数据名称 + * @param string $default 默认值 + * @param string|array $filter 过滤方法 * @return mixed */ public function env($name = '', $default = null, $filter = '') @@ -928,8 +951,8 @@ class Request /** * 设置或者获取当前的Header * @access public - * @param string|array $name header名称 - * @param string $default 默认值 + * @param string|array $name header名称 + * @param string $default 默认值 * @return string */ public function header($name = '', $default = null) @@ -967,10 +990,10 @@ class Request /** * 获取变量 支持过滤和默认值 - * @param array $data 数据源 - * @param string|false $name 字段名 - * @param mixed $default 默认值 - * @param string|array $filter 过滤函数 + * @param array $data 数据源 + * @param string|false $name 字段名 + * @param mixed $default 默认值 + * @param string|array $filter 过滤函数 * @return mixed */ public function input($data = [], $name = '', $default = null, $filter = '') @@ -1051,9 +1074,9 @@ class Request /** * 递归过滤给定的值 - * @param mixed $value 键值 - * @param mixed $key 键名 - * @param array $filters 过滤方法+默认值 + * @param mixed $value 键值 + * @param mixed $key 键名 + * @param array $filters 过滤方法+默认值 * @return mixed */ private function filterValue(&$value, $key, $filters) @@ -1138,9 +1161,9 @@ class Request /** * 是否存在某个请求参数 * @access public - * @param string $name 变量名 - * @param string $type 变量类型 - * @param bool $checkEmpty 是否检测空值 + * @param string $name 变量名 + * @param string $type 变量类型 + * @param bool $checkEmpty 是否检测空值 * @return mixed */ public function has($name, $type = 'param', $checkEmpty = false) @@ -1164,8 +1187,8 @@ class Request /** * 获取指定的参数 * @access public - * @param string|array $name 变量名 - * @param string $type 变量类型 + * @param string|array $name 变量名 + * @param string $type 变量类型 * @return mixed */ public function only($name, $type = 'param') @@ -1186,8 +1209,8 @@ class Request /** * 排除指定参数获取 * @access public - * @param string|array $name 变量名 - * @param string $type 变量类型 + * @param string|array $name 变量名 + * @param string $type 变量类型 * @return mixed */ public function except($name, $type = 'param') @@ -1229,7 +1252,7 @@ class Request /** * 当前是否Ajax请求 * @access public - * @param bool $ajax true 获取原始ajax请求 + * @param bool $ajax true 获取原始ajax请求 * @return bool */ public function isAjax($ajax = false) @@ -1239,14 +1262,16 @@ class Request if (true === $ajax) { return $result; } else { - return $this->param(Config::get('var_ajax')) ? true : $result; + $result = $this->param(Config::get('var_ajax')) ? true : $result; + $this->mergeParam = false; + return $result; } } /** * 当前是否Pjax请求 * @access public - * @param bool $pjax true 获取原始pjax请求 + * @param bool $pjax true 获取原始pjax请求 * @return bool */ public function isPjax($pjax = false) @@ -1255,19 +1280,21 @@ class Request if (true === $pjax) { return $result; } else { - return $this->param(Config::get('var_pjax')) ? true : $result; + $result = $this->param(Config::get('var_pjax')) ? true : $result; + $this->mergeParam = false; + return $result; } } /** * 获取客户端IP地址 - * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 - * @param boolean $adv 是否进行高级模式获取(有可能被伪装) + * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 + * @param boolean $adv 是否进行高级模式获取(有可能被伪装) * @return mixed */ public function ip($type = 0, $adv = true) { - $type = $type ? 1 : 0; + $type = $type ? 1 : 0; static $ip = null; if (null !== $ip) { return $ip[$type]; @@ -1342,7 +1369,7 @@ class Request /** * 当前请求的host * @access public - * @param bool $strict true 仅仅获取HOST + * @param bool $strict true 仅仅获取HOST * @return string */ public function host($strict = false) @@ -1423,7 +1450,7 @@ class Request /** * 设置或者获取当前请求的调度信息 * @access public - * @param array $dispatch 调度信息 + * @param array $dispatch 调度信息 * @return array */ public function dispatch($dispatch = null) @@ -1543,7 +1570,7 @@ class Request /** * 设置当前地址的请求缓存 * @access public - * @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id + * @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id * @param mixed $expire 缓存有效期 * @param array $except 缓存排除 * @param string $tag 缓存标签 @@ -1606,7 +1633,7 @@ class Request throw new \think\exception\HttpResponseException($response); } elseif (Cache::has($key)) { list($content, $header) = Cache::get($key); - $response = Response::create($content)->header($header); + $response = Response::create($content)->header($header); throw new \think\exception\HttpResponseException($response); } else { $this->cache = [$key, $expire, $tag]; @@ -1628,7 +1655,7 @@ class Request * 设置当前请求绑定的对象实例 * @access public * @param string|array $name 绑定的对象标识 - * @param mixed $obj 绑定的对象实例 + * @param mixed $obj 绑定的对象实例 * @return mixed */ public function bind($name, $obj = null) diff --git a/thinkphp/library/think/Route.php b/thinkphp/library/think/Route.php index 99ffa70..ab53aa2 100755 --- a/thinkphp/library/think/Route.php +++ b/thinkphp/library/think/Route.php @@ -68,8 +68,8 @@ class Route /** * 注册变量规则 * @access public - * @param string|array $name 变量名 - * @param string $rule 变量规则 + * @param string|array $name 变量名 + * @param string $rule 变量规则 * @return void */ public static function pattern($name = null, $rule = '') @@ -84,10 +84,10 @@ class Route /** * 注册子域名部署规则 * @access public - * @param string|array $domain 子域名 - * @param mixed $rule 路由规则 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $domain 子域名 + * @param mixed $rule 路由规则 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function domain($domain, $rule = '', $option = [], $pattern = []) @@ -121,8 +121,8 @@ class Route /** * 设置路由绑定 * @access public - * @param mixed $bind 绑定信息 - * @param string $type 绑定类型 默认为module 支持 namespace class controller + * @param mixed $bind 绑定信息 + * @param string $type 绑定类型 默认为module 支持 namespace class controller * @return mixed */ public static function bind($bind, $type = 'module') @@ -133,8 +133,8 @@ class Route /** * 设置或者获取路由标识 * @access public - * @param string|array $name 路由命名标识 数组表示批量设置 - * @param array $value 路由地址及变量信息 + * @param string|array $name 路由命名标识 数组表示批量设置 + * @param array $value 路由地址及变量信息 * @return array */ public static function name($name = '', $value = null) @@ -154,7 +154,7 @@ class Route /** * 读取路由绑定 * @access public - * @param string $type 绑定类型 + * @param string $type 绑定类型 * @return mixed */ public static function getBind($type) @@ -165,8 +165,8 @@ class Route /** * 导入配置文件的路由规则 * @access public - * @param array $rule 路由规则 - * @param string $type 请求类型 + * @param array $rule 路由规则 + * @param string $type 请求类型 * @return void */ public static function import(array $rule, $type = '*') @@ -222,11 +222,11 @@ class Route /** * 注册路由规则 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param string $type 请求类型 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param string $type 请求类型 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function rule($rule, $route = '', $type = '*', $option = [], $pattern = []) @@ -270,12 +270,12 @@ class Route /** * 设置路由规则 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param string $type 请求类型 - * @param array $option 路由参数 - * @param array $pattern 变量规则 - * @param string $group 所属分组 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param string $type 请求类型 + * @param array $option 路由参数 + * @param array $pattern 变量规则 + * @param string $group 所属分组 * @return void */ protected static function setRule($rule, $route, $type = '*', $option = [], $pattern = [], $group = '') @@ -348,7 +348,7 @@ class Route /** * 设置当前执行的参数信息 * @access public - * @param array $options 参数信息 + * @param array $options 参数信息 * @return mixed */ protected static function setOption($options = []) @@ -369,7 +369,7 @@ class Route /** * 获取当前的分组信息 * @access public - * @param string $type 分组信息名称 name option pattern + * @param string $type 分组信息名称 name option pattern * @return mixed */ public static function getGroup($type) @@ -384,9 +384,9 @@ class Route /** * 设置当前的路由分组 * @access public - * @param string $name 分组名称 - * @param array $option 分组路由参数 - * @param array $pattern 分组变量规则 + * @param string $name 分组名称 + * @param array $option 分组路由参数 + * @param array $pattern 分组变量规则 * @return void */ public static function setGroup($name, $option = [], $pattern = []) @@ -399,10 +399,10 @@ class Route /** * 注册路由分组 * @access public - * @param string|array $name 分组名称或者参数 - * @param array|\Closure $routes 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $name 分组名称或者参数 + * @param array|\Closure $routes 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function group($name, $routes, $option = [], $pattern = []) @@ -487,10 +487,10 @@ class Route /** * 注册路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function any($rule, $route = '', $option = [], $pattern = []) @@ -501,10 +501,10 @@ class Route /** * 注册GET路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function get($rule, $route = '', $option = [], $pattern = []) @@ -515,10 +515,10 @@ class Route /** * 注册POST路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function post($rule, $route = '', $option = [], $pattern = []) @@ -529,10 +529,10 @@ class Route /** * 注册PUT路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function put($rule, $route = '', $option = [], $pattern = []) @@ -543,10 +543,10 @@ class Route /** * 注册DELETE路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function delete($rule, $route = '', $option = [], $pattern = []) @@ -557,10 +557,10 @@ class Route /** * 注册PATCH路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function patch($rule, $route = '', $option = [], $pattern = []) @@ -571,10 +571,10 @@ class Route /** * 注册资源路由 * @access public - * @param string|array $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string|array $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function resource($rule, $route = '', $option = [], $pattern = []) @@ -618,10 +618,10 @@ class Route /** * 注册控制器路由 操作方法对应不同的请求后缀 * @access public - * @param string $rule 路由规则 - * @param string $route 路由地址 - * @param array $option 路由参数 - * @param array $pattern 变量规则 + * @param string $rule 路由规则 + * @param string $route 路由地址 + * @param array $option 路由参数 + * @param array $pattern 变量规则 * @return void */ public static function controller($rule, $route = '', $option = [], $pattern = []) @@ -634,9 +634,9 @@ class Route /** * 注册别名路由 * @access public - * @param string|array $rule 路由别名 - * @param string $route 路由地址 - * @param array $option 路由参数 + * @param string|array $rule 路由别名 + * @param string $route 路由地址 + * @param array $option 路由参数 * @return void */ public static function alias($rule = null, $route = '', $option = []) @@ -651,8 +651,8 @@ class Route /** * 设置不同请求类型下面的方法前缀 * @access public - * @param string $method 请求类型 - * @param string $prefix 类型前缀 + * @param string $method 请求类型 + * @param string $prefix 类型前缀 * @return void */ public static function setMethodPrefix($method, $prefix = '') @@ -667,8 +667,8 @@ class Route /** * rest方法定义和修改 * @access public - * @param string|array $name 方法名称 - * @param array|bool $resource 资源 + * @param string|array $name 方法名称 + * @param array|bool $resource 资源 * @return void */ public static function rest($name, $resource = []) @@ -683,9 +683,9 @@ class Route /** * 注册未匹配路由规则后的处理 * @access public - * @param string $route 路由地址 - * @param string $method 请求类型 - * @param array $option 路由参数 + * @param string $route 路由地址 + * @param string $method 请求类型 + * @param array $option 路由参数 * @return void */ public static function miss($route, $method = '*', $option = []) @@ -696,7 +696,7 @@ class Route /** * 注册一个自动解析的URL路由 * @access public - * @param string $route 路由地址 + * @param string $route 路由地址 * @return void */ public static function auto($route) @@ -726,9 +726,9 @@ class Route /** * 检测子域名部署 * @access public - * @param Request $request Request请求对象 - * @param array $currentRules 当前路由规则 - * @param string $method 请求类型 + * @param Request $request Request请求对象 + * @param array $currentRules 当前路由规则 + * @param string $method 请求类型 * @return void */ public static function checkDomain($request, &$currentRules, $method = 'get') @@ -827,14 +827,23 @@ class Route /** * 检测URL路由 * @access public - * @param Request $request Request请求对象 - * @param string $url URL地址 - * @param string $depr URL分隔符 - * @param bool $checkDomain 是否检测域名规则 + * @param Request $request Request请求对象 + * @param string $url URL地址 + * @param string $depr URL分隔符 + * @param bool $checkDomain 是否检测域名规则 * @return false|array */ public static function check($request, $url, $depr = '/', $checkDomain = false) { + //检查解析缓存 + if (!App::$debug && Config::get('route_check_cache')) { + $key = self::getCheckCacheKey($request); + if (Cache::has($key)) { + list($rule, $route, $pathinfo, $option, $matches) = Cache::get($key); + return self::parseRule($rule, $route, $pathinfo, $option, $matches, true); + } + } + // 分隔符替换 确保路由定义使用统一的分隔符 $url = str_replace($depr, '|', $url); @@ -888,12 +897,12 @@ class Route /** * 检测路由规则 * @access private - * @param Request $request - * @param array $rules 路由规则 - * @param string $url URL地址 - * @param string $depr URL分割符 - * @param string $group 路由分组名 - * @param array $options 路由参数(分组) + * @param Request $request + * @param array $rules 路由规则 + * @param string $url URL地址 + * @param string $depr URL分割符 + * @param string $group 路由分组名 + * @param array $options 路由参数(分组) * @return mixed */ private static function checkRoute($request, $rules, $url, $depr = '/', $group = '', $options = []) @@ -971,9 +980,9 @@ class Route /** * 检测路由别名 * @access private - * @param Request $request - * @param string $url URL地址 - * @param string $depr URL分隔符 + * @param Request $request + * @param string $url URL地址 + * @param string $depr URL分隔符 * @return mixed */ private static function checkRouteAlias($request, $url, $depr) @@ -1018,9 +1027,9 @@ class Route /** * 检测URL绑定 * @access private - * @param string $url URL地址 - * @param array $rules 路由规则 - * @param string $depr URL分隔符 + * @param string $url URL地址 + * @param array $rules 路由规则 + * @param string $depr URL分隔符 * @return mixed */ private static function checkUrlBind(&$url, &$rules, $depr = '/') @@ -1049,9 +1058,9 @@ class Route /** * 绑定到类 * @access public - * @param string $url URL地址 - * @param string $class 类名(带命名空间) - * @param string $depr URL分隔符 + * @param string $url URL地址 + * @param string $class 类名(带命名空间) + * @param string $depr URL分隔符 * @return array */ public static function bindToClass($url, $class, $depr = '/') @@ -1068,9 +1077,9 @@ class Route /** * 绑定到命名空间 * @access public - * @param string $url URL地址 - * @param string $namespace 命名空间 - * @param string $depr URL分隔符 + * @param string $url URL地址 + * @param string $namespace 命名空间 + * @param string $depr URL分隔符 * @return array */ public static function bindToNamespace($url, $namespace, $depr = '/') @@ -1088,9 +1097,9 @@ class Route /** * 绑定到控制器类 * @access public - * @param string $url URL地址 - * @param string $controller 控制器名 (支持带模块名 index/user ) - * @param string $depr URL分隔符 + * @param string $url URL地址 + * @param string $controller 控制器名 (支持带模块名 index/user ) + * @param string $depr URL分隔符 * @return array */ public static function bindToController($url, $controller, $depr = '/') @@ -1107,9 +1116,9 @@ class Route /** * 绑定到模块/控制器 * @access public - * @param string $url URL地址 - * @param string $controller 控制器类名(带命名空间) - * @param string $depr URL分隔符 + * @param string $url URL地址 + * @param string $controller 控制器类名(带命名空间) + * @param string $depr URL分隔符 * @return array */ public static function bindToModule($url, $controller, $depr = '/') @@ -1126,8 +1135,8 @@ class Route /** * 路由参数有效性检查 * @access private - * @param array $option 路由参数 - * @param Request $request Request对象 + * @param array $option 路由参数 + * @param Request $request Request对象 * @return bool */ private static function checkOption($option, $request) @@ -1153,12 +1162,12 @@ class Route /** * 检测路由规则 * @access private - * @param string $rule 路由规则 - * @param string $route 路由地址 - * @param string $url URL地址 - * @param array $pattern 变量规则 - * @param array $option 路由参数 - * @param string $depr URL分隔符(全局) + * @param string $rule 路由规则 + * @param string $route 路由地址 + * @param string $url URL地址 + * @param array $pattern 变量规则 + * @param array $option 路由参数 + * @param string $depr URL分隔符(全局) * @return array|false */ private static function checkRule($rule, $route, $url, $pattern, $option, $depr) @@ -1200,9 +1209,9 @@ class Route /** * 解析模块的URL地址 [模块/控制器/操作?]参数1=值1&参数2=值2... * @access public - * @param string $url URL地址 - * @param string $depr URL分隔符 - * @param bool $autoSearch 是否自动深度搜索控制器 + * @param string $url URL地址 + * @param string $depr URL分隔符 + * @param bool $autoSearch 是否自动深度搜索控制器 * @return array */ public static function parseUrl($url, $depr = '/', $autoSearch = false) @@ -1269,7 +1278,7 @@ class Route /** * 解析URL的pathinfo参数和变量 * @access private - * @param string $url URL地址 + * @param string $url URL地址 * @return array */ private static function parseUrlPath($url) @@ -1295,9 +1304,9 @@ class Route /** * 检测URL和规则路由是否匹配 * @access private - * @param string $url URL地址 - * @param string $rule 路由规则 - * @param array $pattern 变量规则 + * @param string $url URL地址 + * @param string $rule 路由规则 + * @param array $pattern 变量规则 * @return array|false */ private static function match($url, $rule, $pattern) @@ -1370,16 +1379,28 @@ class Route /** * 解析规则路由 * @access private - * @param string $rule 路由规则 - * @param string $route 路由地址 - * @param string $pathinfo URL地址 - * @param array $option 路由参数 - * @param array $matches 匹配的变量 + * @param string $rule 路由规则 + * @param string $route 路由地址 + * @param string $pathinfo URL地址 + * @param array $option 路由参数 + * @param array $matches 匹配的变量 + * @param bool $fromCache 通过缓存解析 * @return array */ - private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = []) + private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = [], $fromCache = false) { $request = Request::instance(); + + //保存解析缓存 + if (Config::get('route_check_cache') && !$fromCache) { + try { + $key = self::getCheckCacheKey($request); + Cache::tag('route_check')->set($key, [$rule, $route, $pathinfo, $option, $matches]); + } catch (\Exception $e) { + + } + } + // 解析路由规则 if ($rule) { $rule = explode('/', $rule); @@ -1526,8 +1547,8 @@ class Route /** * 解析URL地址为 模块/控制器/操作 * @access private - * @param string $url URL地址 - * @param bool $convert 是否自动转换URL地址 + * @param string $url URL地址 + * @param bool $convert 是否自动转换URL地址 * @return array */ private static function parseModule($url, $convert = false) @@ -1550,8 +1571,8 @@ class Route /** * 解析URL地址中的参数Request对象 * @access private - * @param string $url 路由规则 - * @param array $var 变量 + * @param string $url 路由规则 + * @param array $var 变量 * @return void */ private static function parseUrlParams($url, &$var = []) @@ -1601,4 +1622,24 @@ class Route } return $var; } + + /** + * 获取路由解析缓存的key + * @param Request $request + * @return string + */ + private static function getCheckCacheKey(Request $request) + { + static $key; + + if (empty($key)) { + if ($callback = Config::get('route_check_cache_key')) { + $key = call_user_func($callback, $request); + } else { + $key = "{$request->host(true)}|{$request->method()}|{$request->path()}"; + } + } + + return $key; + } } diff --git a/thinkphp/library/think/Url.php b/thinkphp/library/think/Url.php index bb69719..53a545f 100755 --- a/thinkphp/library/think/Url.php +++ b/thinkphp/library/think/Url.php @@ -239,7 +239,7 @@ class Url $rootDomain = Config::get('url_domain_root'); if (true === $domain) { // 自动判断域名 - $domain = Config::get('app_host') ?: $request->host(true); + $domain = Config::get('app_host') ?: $request->host(); $domains = Route::rules('domain'); if ($domains) { diff --git a/thinkphp/library/think/Validate.php b/thinkphp/library/think/Validate.php index 6226892..df6c6e7 100755 --- a/thinkphp/library/think/Validate.php +++ b/thinkphp/library/think/Validate.php @@ -67,6 +67,8 @@ class Validate 'min' => 'min size of :attribute must be :rule', 'after' => ':attribute cannot be less than :rule', 'before' => ':attribute cannot exceed :rule', + 'afterWith' => ':attribute cannot be less than :rule', + 'beforeWith' => ':attribute cannot exceed :rule', 'expire' => ':attribute not within :rule', 'allowIp' => 'access IP is not allowed', 'denyIp' => 'access IP denied', @@ -1113,9 +1115,10 @@ class Validate * @access protected * @param mixed $value 字段值 * @param mixed $rule 验证规则 + * @param array $data 数据 * @return bool */ - protected function after($value, $rule) + protected function after($value, $rule, $data) { return strtotime($value) >= strtotime($rule); } @@ -1125,13 +1128,42 @@ class Validate * @access protected * @param mixed $value 字段值 * @param mixed $rule 验证规则 + * @param array $data 数据 * @return bool */ - protected function before($value, $rule) + protected function before($value, $rule, $data) { return strtotime($value) <= strtotime($rule); } + /** + * 验证日期字段 + * @access protected + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @param array $data 数据 + * @return bool + */ + protected function afterWith($value, $rule, $data) + { + $rule = $this->getDataValue($data, $rule); + return !is_null($rule) && strtotime($value) >= strtotime($rule); + } + + /** + * 验证日期字段 + * @access protected + * @param mixed $value 字段值 + * @param mixed $rule 验证规则 + * @param array $data 数据 + * @return bool + */ + protected function beforeWith($value, $rule, $data) + { + $rule = $this->getDataValue($data, $rule); + return !is_null($rule) && strtotime($value) <= strtotime($rule); + } + /** * 验证有效期 * @access protected diff --git a/thinkphp/library/think/cache/driver/Memcache.php b/thinkphp/library/think/cache/driver/Memcache.php index 815f60b..58703ea 100755 --- a/thinkphp/library/think/cache/driver/Memcache.php +++ b/thinkphp/library/think/cache/driver/Memcache.php @@ -63,7 +63,7 @@ class Memcache extends Driver public function has($name) { $key = $this->getCacheKey($name); - return $this->handler->get($key) ? true : false; + return false !== $this->handler->get($key); } /** diff --git a/thinkphp/library/think/cache/driver/Redis.php b/thinkphp/library/think/cache/driver/Redis.php index bb8713a..027b3ea 100755 --- a/thinkphp/library/think/cache/driver/Redis.php +++ b/thinkphp/library/think/cache/driver/Redis.php @@ -70,7 +70,7 @@ class Redis extends Driver */ public function has($name) { - return $this->handler->get($this->getCacheKey($name)) ? true : false; + return $this->handler->exists($this->getCacheKey($name)); } /** diff --git a/thinkphp/library/think/console/command/Clear.php b/thinkphp/library/think/console/command/Clear.php index 41019ce..1b5102e 100755 --- a/thinkphp/library/think/console/command/Clear.php +++ b/thinkphp/library/think/console/command/Clear.php @@ -10,8 +10,10 @@ // +---------------------------------------------------------------------- namespace think\console\command; +use think\Cache; use think\console\Command; use think\console\Input; +use think\console\input\Argument; use think\console\input\Option; use think\console\Output; @@ -22,6 +24,7 @@ class Clear extends Command // 指令配置 $this ->setName('clear') + ->addArgument('type', Argument::OPTIONAL, 'type to clear', null) ->addOption('path', 'd', Option::VALUE_OPTIONAL, 'path to clear', null) ->setDescription('Clear runtime file'); } @@ -30,8 +33,14 @@ class Clear extends Command { $path = $input->getOption('path') ?: RUNTIME_PATH; - if (is_dir($path)) { - $this->clearPath($path); + $type = $input->getArgument('type'); + + if ($type == 'route') { + Cache::clear('route_check'); + } else { + if (is_dir($path)) { + $this->clearPath($path); + } } $output->writeln("Clear Successed"); diff --git a/thinkphp/library/think/db/Builder.php b/thinkphp/library/think/db/Builder.php index d4d27a1..58b45aa 100755 --- a/thinkphp/library/think/db/Builder.php +++ b/thinkphp/library/think/db/Builder.php @@ -98,6 +98,10 @@ abstract class Builder $result = []; foreach ($data as $key => $val) { + if ('*' != $options['field'] && !in_array($key, $fields, true)) { + continue; + } + $item = $this->parseKey($key, $options, true); if ($val instanceof Expression) { $result[$item] = $val->getValue(); @@ -113,13 +117,15 @@ abstract class Builder } elseif (is_null($val)) { $result[$item] = 'NULL'; } elseif (is_array($val) && !empty($val)) { - switch ($val[0]) { + switch (strtolower($val[0])) { case 'inc': $result[$item] = $item . '+' . floatval($val[1]); break; case 'dec': $result[$item] = $item . '-' . floatval($val[1]); break; + case 'exp': + throw new Exception('not support data:[' . $val[0] . ']'); } } elseif (is_scalar($val)) { // 过滤非标量数据 @@ -267,9 +273,7 @@ abstract class Builder foreach ($val as $field => $value) { if ($value instanceof Expression) { $str[] = ' ' . $key . ' ( ' . $value->getValue() . ' )'; - continue; - } - if ($value instanceof \Closure) { + } elseif ($value instanceof \Closure) { // 使用闭包查询 $query = new Query($this->connection); call_user_func_array($value, [ & $query]); @@ -628,7 +632,7 @@ abstract class Builder protected function parseComment($comment) { if (false !== strpos($comment, '*/')) { - $comment = strstr($coment, '*/', true); + $comment = strstr($comment, '*/', true); } return !empty($comment) ? ' /* ' . $comment . ' */' : ''; } @@ -802,7 +806,7 @@ abstract class Builder } foreach ($insertFields as $field) { - $fields[] = $this->parseKey($query, $field, true); + $fields[] = $this->parseKey($field, $options, true); } return str_replace( diff --git a/thinkphp/library/think/db/Connection.php b/thinkphp/library/think/db/Connection.php index 7720282..578cc8f 100755 --- a/thinkphp/library/think/db/Connection.php +++ b/thinkphp/library/think/db/Connection.php @@ -361,14 +361,9 @@ abstract class Connection // 调试开始 $this->debug(true); - // 释放前次的查询结果 - if (!empty($this->PDOStatement)) { - $this->free(); - } // 预处理 - if (empty($this->PDOStatement)) { - $this->PDOStatement = $this->linkID->prepare($sql); - } + $this->PDOStatement = $this->linkID->prepare($sql); + // 是否为存储过程调用 $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); // 参数绑定 @@ -429,14 +424,9 @@ abstract class Connection // 调试开始 $this->debug(true); - //释放前次的查询结果 - if (!empty($this->PDOStatement) && $this->PDOStatement->queryString != $sql) { - $this->free(); - } // 预处理 - if (empty($this->PDOStatement)) { - $this->PDOStatement = $this->linkID->prepare($sql); - } + $this->PDOStatement = $this->linkID->prepare($sql); + // 是否为存储过程调用 $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']); // 参数绑定 @@ -659,18 +649,15 @@ abstract class Connection ); } - } catch (\PDOException $e) { - if ($this->isBreak($e)) { - return $this->close()->startTrans(); - } - throw $e; } catch (\Exception $e) { if ($this->isBreak($e)) { + --$this->transTimes; return $this->close()->startTrans(); } throw $e; } catch (\Error $e) { if ($this->isBreak($e)) { + --$this->transTimes; return $this->close()->startTrans(); } throw $e; @@ -804,6 +791,8 @@ abstract class Connection $this->linkWrite = null; $this->linkRead = null; $this->links = []; + // 释放查询 + $this->free(); return $this; } diff --git a/thinkphp/library/think/db/Query.php b/thinkphp/library/think/db/Query.php index 1f3ddc2..75086bc 100755 --- a/thinkphp/library/think/db/Query.php +++ b/thinkphp/library/think/db/Query.php @@ -92,6 +92,13 @@ class Query $name = Loader::parseName(substr($method, 10)); $where[$name] = $args[0]; return $this->where($where)->value($args[1]); + } elseif ($this->model && method_exists($this->model, 'scope' . $method)) { + // 动态调用命名范围 + $method = 'scope' . $method; + array_unshift($args, $this); + + call_user_func_array([$this->model, $method], $args); + return $this; } else { throw new Exception('method not exist:' . __CLASS__ . '->' . $method); } @@ -436,12 +443,13 @@ class Query // 返回SQL语句 return $pdo; } + $result = $pdo->fetchColumn(); if ($force) { - $result += 0; + $result = (float) $result; } - if (isset($cache)) { + if (isset($cache) && false !== $result) { // 缓存数据 $this->cacheData($key, $result, $cache); } @@ -531,13 +539,43 @@ class Query public function count($field = '*') { if (isset($this->options['group'])) { + if (!preg_match('/^[\w\.\*]+$/', $field)) { + throw new Exception('not support data:' . $field); + } // 支持GROUP $options = $this->getOptions(); $subSql = $this->options($options)->field('count(' . $field . ')')->bind($this->bind)->buildSql(); - return $this->table([$subSql => '_group_count_'])->value('COUNT(*) AS tp_count', 0, true); + + $count = $this->table([$subSql => '_group_count_'])->value('COUNT(*) AS tp_count', 0, true); + } else { + $count = $this->aggregate('COUNT', $field, true); } - return $this->value('COUNT(' . $field . ') AS tp_count', 0, true); + return is_string($count) ? $count : (int) $count; + + } + + /** + * 聚合查询 + * @access public + * @param string $aggregate 聚合方法 + * @param string $field 字段名 + * @param bool $force 强制转为数字类型 + * @return mixed + */ + public function aggregate($aggregate, $field, $force = false) + { + if (0 === stripos($field, 'DISTINCT ')) { + list($distinct, $field) = explode(' ', $field); + } + + if (!preg_match('/^[\w\.\+\-\*]+$/', $field)) { + throw new Exception('not support data:' . $field); + } + + $result = $this->value($aggregate . '(' . (!empty($distinct) ? 'DISTINCT ' : '') . $field . ') AS tp_' . strtolower($aggregate), 0, $force); + + return $result; } /** @@ -548,7 +586,7 @@ class Query */ public function sum($field) { - return $this->value('SUM(' . $field . ') AS tp_sum', 0, true); + return $this->aggregate('SUM', $field, true); } /** @@ -560,7 +598,7 @@ class Query */ public function min($field, $force = true) { - return $this->value('MIN(' . $field . ') AS tp_min', 0, $force); + return $this->aggregate('MIN', $field, $force); } /** @@ -572,7 +610,7 @@ class Query */ public function max($field, $force = true) { - return $this->value('MAX(' . $field . ') AS tp_max', 0, $force); + return $this->aggregate('MAX', $field, $force); } /** @@ -583,7 +621,7 @@ class Query */ public function avg($field) { - return $this->value('AVG(' . $field . ') AS tp_avg', 0, true); + return $this->aggregate('AVG', $field, true); } /** @@ -2092,14 +2130,23 @@ class Query $this->field('*'); } foreach ($relations as $key => $relation) { - $closure = false; + $closure = $name = null; if ($relation instanceof \Closure) { $closure = $relation; $relation = $key; + } elseif (!is_int($key)) { + $name = $relation; + $relation = $key; } $relation = Loader::parseName($relation, 1, false); - $count = '(' . $this->model->$relation()->getRelationCountQuery($closure) . ')'; - $this->field([$count => Loader::parseName($relation) . '_count']); + + $count = '(' . $this->model->$relation()->getRelationCountQuery($closure, $name) . ')'; + + if (empty($name)) { + $name = Loader::parseName($relation) . '_count'; + } + + $this->field([$count => $name]); } } return $this; diff --git a/thinkphp/library/think/db/builder/Mysql.php b/thinkphp/library/think/db/builder/Mysql.php index 8eee746..be2af71 100755 --- a/thinkphp/library/think/db/builder/Mysql.php +++ b/thinkphp/library/think/db/builder/Mysql.php @@ -109,6 +109,9 @@ class Mysql extends Builder } } + if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) { + throw new Exception('not support data:' . $key); + } if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)`.\s]/', $key))) { $key = '`' . $key . '`'; } diff --git a/thinkphp/library/think/db/builder/Sqlsrv.php b/thinkphp/library/think/db/builder/Sqlsrv.php index f79ae03..dc425d9 100755 --- a/thinkphp/library/think/db/builder/Sqlsrv.php +++ b/thinkphp/library/think/db/builder/Sqlsrv.php @@ -94,6 +94,10 @@ class Sqlsrv extends Builder $table = $options['alias'][$table]; } } + + if ($strict && !preg_match('/^[\w\.\*]+$/', $key)) { + throw new Exception('not support data:' . $key); + } if ('*' != $key && ($strict || !preg_match('/[,\'\"\*\(\)\[.\s]/', $key))) { $key = '[' . $key . ']'; } diff --git a/thinkphp/library/think/db/connector/Sqlsrv.php b/thinkphp/library/think/db/connector/Sqlsrv.php index 08ad45e..35c6600 100755 --- a/thinkphp/library/think/db/connector/Sqlsrv.php +++ b/thinkphp/library/think/db/connector/Sqlsrv.php @@ -50,7 +50,10 @@ class Sqlsrv extends Connection public function getFields($tableName) { list($tableName) = explode(' ', $tableName); - $sql = "SELECT column_name, data_type, column_default, is_nullable + $tableNames = explode('.', $tableName); + $tableName = isset($tableNames[1]) ? $tableNames[1] : $tableNames[0]; + + $sql = "SELECT column_name, data_type, column_default, is_nullable FROM information_schema.tables AS t JOIN information_schema.columns AS c ON t.table_catalog = c.table_catalog diff --git a/thinkphp/library/think/log/driver/File.php b/thinkphp/library/think/log/driver/File.php index fa84ac1..f2296cf 100755 --- a/thinkphp/library/think/log/driver/File.php +++ b/thinkphp/library/think/log/driver/File.php @@ -26,10 +26,9 @@ class File 'path' => LOG_PATH, 'apart_level' => [], 'max_files' => 0, + 'json' => false, ]; - protected $writed = []; - // 实例化并传入参数 public function __construct($config = []) { @@ -41,106 +40,231 @@ class File /** * 日志写入接口 * @access public - * @param array $log 日志信息 + * @param array $log 日志信息 + * @param bool $append 是否追加请求信息 * @return bool */ - public function save(array $log = []) + public function save(array $log = [], $append = false) + { + $destination = $this->getMasterLogFile(); + + $path = dirname($destination); + !is_dir($path) && mkdir($path, 0755, true); + + $info = []; + foreach ($log as $type => $val) { + + foreach ($val as $msg) { + if (!is_string($msg)) { + $msg = var_export($msg, true); + } + + $info[$type][] = $this->config['json'] ? $msg : '[ ' . $type . ' ] ' . $msg; + } + + if (!$this->config['json'] && (true === $this->config['apart_level'] || in_array($type, $this->config['apart_level']))) { + // 独立记录的日志级别 + $filename = $this->getApartLevelFile($path, $type); + + $this->write($info[$type], $filename, true, $append); + unset($info[$type]); + } + } + + if ($info) { + return $this->write($info, $destination, false, $append); + } + + return true; + } + + /** + * 获取主日志文件名 + * @access public + * @return string + */ + protected function getMasterLogFile() { if ($this->config['single']) { - $destination = $this->config['path'] . 'single.log'; + $name = is_string($this->config['single']) ? $this->config['single'] : 'single'; + + $destination = $this->config['path'] . $name . '.log'; } else { - $cli = IS_CLI ? '_cli' : ''; + $cli = PHP_SAPI == 'cli' ? '_cli' : ''; if ($this->config['max_files']) { $filename = date('Ymd') . $cli . '.log'; $files = glob($this->config['path'] . '*.log'); - if (count($files) > $this->config['max_files']) { - unlink($files[0]); + try { + if (count($files) > $this->config['max_files']) { + unlink($files[0]); + } + } catch (\Exception $e) { } } else { - $filename = date('Ym') . '/' . date('d') . $cli . '.log'; + $filename = date('Ym') . DIRECTORY_SEPARATOR . date('d') . $cli . '.log'; } $destination = $this->config['path'] . $filename; } - $path = dirname($destination); - !is_dir($path) && mkdir($path, 0755, true); - - $info = ''; - foreach ($log as $type => $val) { - $level = ''; - foreach ($val as $msg) { - if (!is_string($msg)) { - $msg = var_export($msg, true); - } - $level .= '[ ' . $type . ' ] ' . $msg . "\r\n"; - } - if (in_array($type, $this->config['apart_level'])) { - // 独立记录的日志级别 - if ($this->config['single']) { - $filename = $path . DS . $type . '.log'; - } elseif ($this->config['max_files']) { - $filename = $path . DS . date('Ymd') . '_' . $type . $cli . '.log'; - } else { - $filename = $path . DS . date('d') . '_' . $type . $cli . '.log'; - } - $this->write($level, $filename, true); - } else { - $info .= $level; - } - } - if ($info) { - return $this->write($info, $destination); - } - return true; + return $destination; } - protected function write($message, $destination, $apart = false) + /** + * 获取独立日志文件名 + * @access public + * @param string $path 日志目录 + * @param string $type 日志类型 + * @return string + */ + protected function getApartLevelFile($path, $type) { - //检测日志文件大小,超过配置大小则备份日志文件重新生成 - if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) { - try { - rename($destination, dirname($destination) . DS . time() . '-' . basename($destination)); - } catch (\Exception $e) { - } - $this->writed[$destination] = false; + $cli = PHP_SAPI == 'cli' ? '_cli' : ''; + + if ($this->config['single']) { + $name = is_string($this->config['single']) ? $this->config['single'] : 'single'; + + $name .= '_' . $type; + } elseif ($this->config['max_files']) { + $name = date('Ymd') . '_' . $type . $cli; + } else { + $name = date('d') . '_' . $type . $cli; } - if (empty($this->writed[$destination]) && !IS_CLI) { - if (App::$debug && !$apart) { - // 获取基本信息 - if (isset($_SERVER['HTTP_HOST'])) { - $current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; - } else { - $current_uri = "cmd:" . implode(' ', $_SERVER['argv']); - } + return $path . DIRECTORY_SEPARATOR . $name . '.log'; + } - $runtime = round(microtime(true) - THINK_START_TIME, 10); - $reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞'; - $time_str = ' [运行时间:' . number_format($runtime, 6) . 's][吞吐率:' . $reqs . 'req/s]'; - $memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2); - $memory_str = ' [内存消耗:' . $memory_use . 'kb]'; - $file_load = ' [文件加载:' . count(get_included_files()) . ']'; + /** + * 日志写入 + * @access protected + * @param array $message 日志信息 + * @param string $destination 日志文件 + * @param bool $apart 是否独立文件写入 + * @param bool $append 是否追加请求信息 + * @return bool + */ + protected function write($message, $destination, $apart = false, $append = false) + { + // 检测日志文件大小,超过配置大小则备份日志文件重新生成 + $this->checkLogSize($destination); - $message = '[ info ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n" . $message; - } - $now = date($this->config['time_format']); - $ip = Request::instance()->ip(); - $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI'; - $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : ''; - $message = "---------------------------------------------------------------\r\n[{$now}] {$ip} {$method} {$uri}\r\n" . $message; + // 日志信息封装 + $info['timestamp'] = date($this->config['time_format']); - $this->writed[$destination] = true; + foreach ($message as $type => $msg) { + $info[$type] = is_array($msg) ? implode("\r\n", $msg) : $msg; } - if (IS_CLI) { - $now = date($this->config['time_format']); - $message = "[{$now}]" . $message; + if (PHP_SAPI == 'cli') { + $message = $this->parseCliLog($info); + } else { + // 添加调试日志 + $this->getDebugLog($info, $append, $apart); + + $message = $this->parseLog($info); } return error_log($message, 3, $destination); } + /** + * 检查日志文件大小并自动生成备份文件 + * @access protected + * @param string $destination 日志文件 + * @return void + */ + protected function checkLogSize($destination) + { + if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) { + try { + rename($destination, dirname($destination) . DIRECTORY_SEPARATOR . time() . '-' . basename($destination)); + } catch (\Exception $e) { + } + } + } + + /** + * CLI日志解析 + * @access protected + * @param array $info 日志信息 + * @return string + */ + protected function parseCliLog($info) + { + if ($this->config['json']) { + $message = json_encode($info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\r\n"; + } else { + $now = $info['timestamp']; + unset($info['timestamp']); + + $message = implode("\r\n", $info); + + $message = "[{$now}]" . $message . "\r\n"; + } + + return $message; + } + + /** + * 解析日志 + * @access protected + * @param array $info 日志信息 + * @return string + */ + protected function parseLog($info) + { + $request = Request::instance(); + $requestInfo = [ + 'ip' => $request->ip(), + 'method' => $request->method(), + 'host' => $request->host(), + 'uri' => $request->url(), + ]; + + if ($this->config['json']) { + $info = $requestInfo + $info; + return json_encode($info, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . "\r\n"; + } + + array_unshift($info, "---------------------------------------------------------------\r\n[{$info['timestamp']}] {$requestInfo['ip']} {$requestInfo['method']} {$requestInfo['host']}{$requestInfo['uri']}"); + unset($info['timestamp']); + + return implode("\r\n", $info) . "\r\n"; + } + + protected function getDebugLog(&$info, $append, $apart) + { + if (App::$debug && $append) { + + if ($this->config['json']) { + // 获取基本信息 + $runtime = round(microtime(true) - THINK_START_TIME, 10); + $reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞'; + + $memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2); + + $info = [ + 'runtime' => number_format($runtime, 6) . 's', + 'reqs' => $reqs . 'req/s', + 'memory' => $memory_use . 'kb', + 'file' => count(get_included_files()), + ] + $info; + + } elseif (!$apart) { + // 增加额外的调试信息 + $runtime = round(microtime(true) - THINK_START_TIME, 10); + $reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞'; + + $memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2); + + $time_str = '[运行时间:' . number_format($runtime, 6) . 's] [吞吐率:' . $reqs . 'req/s]'; + $memory_str = ' [内存消耗:' . $memory_use . 'kb]'; + $file_load = ' [文件加载:' . count(get_included_files()) . ']'; + + array_unshift($info, $time_str . $memory_str . $file_load); + } + } + } } diff --git a/thinkphp/library/think/log/driver/Socket.php b/thinkphp/library/think/log/driver/Socket.php index d30bba3..4f62915 100755 --- a/thinkphp/library/think/log/driver/Socket.php +++ b/thinkphp/library/think/log/driver/Socket.php @@ -60,7 +60,7 @@ class Socket * @param array $log 日志信息 * @return bool */ - public function save(array $log = []) + public function save(array $log = [], $append = false) { if (!$this->check()) { return false; diff --git a/thinkphp/library/think/model/relation/BelongsToMany.php b/thinkphp/library/think/model/relation/BelongsToMany.php index c9845a9..a41c45c 100755 --- a/thinkphp/library/think/model/relation/BelongsToMany.php +++ b/thinkphp/library/think/model/relation/BelongsToMany.php @@ -29,6 +29,8 @@ class BelongsToMany extends Relation protected $pivotName; // 中间表模型对象 protected $pivot; + // 中间表数据名称 + protected $pivotDataName = 'pivot'; /** * 构造函数 @@ -71,17 +73,43 @@ class BelongsToMany extends Relation } /** - * 实例化中间表模型 + * 设置中间表数据名称 + * @access public + * @param string $name + * @return $this + */ + public function pivotDataName($name) + { + $this->pivotDataName = $name; + return $this; + } + + /** + * 获取中间表更新条件 * @param $data + * @return array + */ + protected function getUpdateWhere($data) + { + return [ + $this->localKey => $data[$this->localKey], + $this->foreignKey => $data[$this->foreignKey], + ]; + } + + /** + * 实例化中间表模型 + * @param array $data + * @param bool $isUpdate * @return Pivot * @throws Exception */ - protected function newPivot($data = []) + protected function newPivot($data = [], $isUpdate = false) { $class = $this->pivotName ?: '\\think\\model\\Pivot'; $pivot = new $class($data, $this->parent, $this->middle); if ($pivot instanceof Pivot) { - return $pivot; + return $isUpdate ? $pivot->isUpdate(true, $this->getUpdateWhere($data)) : $pivot; } else { throw new Exception('pivot model must extends: \think\model\Pivot'); } @@ -104,7 +132,7 @@ class BelongsToMany extends Relation } } } - $model->setRelation('pivot', $this->newPivot($pivot)); + $model->setRelation($this->pivotDataName, $this->newPivot($pivot, true)); } } @@ -332,10 +360,18 @@ class BelongsToMany extends Relation * 获取关联统计子查询 * @access public * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 * @return string */ - public function getRelationCountQuery($closure) + public function getRelationCountQuery($closure, &$name = null) { + if ($closure) { + $return = call_user_func_array($closure, [ & $this->query]); + if ($return && is_string($return)) { + $name = $return; + } + } + return $this->belongsToManyQuery($this->foreignKey, $this->localKey, [ 'pivot.' . $this->localKey => [ 'exp', @@ -370,7 +406,7 @@ class BelongsToMany extends Relation } } } - $set->setRelation('pivot', $this->newPivot($pivot)); + $set->setRelation($this->pivotDataName, $this->newPivot($pivot, true)); $data[$pivot[$this->localKey]][] = $set; } return $data; @@ -473,7 +509,7 @@ class BelongsToMany extends Relation foreach ($ids as $id) { $pivot[$this->foreignKey] = $id; $this->pivot->insert($pivot, true); - $result[] = $this->newPivot($pivot); + $result[] = $this->newPivot($pivot, true); } if (count($result) == 1) { // 返回中间表模型对象 @@ -485,6 +521,29 @@ class BelongsToMany extends Relation } } + /** + * 判断是否存在关联数据 + * @access public + * @param mixed $data 数据 可以使用关联模型对象 或者 关联对象的主键 + * @return Pivot + * @throws Exception + */ + public function attached($data) + { + if ($data instanceof Model) { + $relationFk = $data->getPk(); + $id = $data->$relationFk; + } else { + $id = $data; + } + + $pk = $this->parent->getPk(); + + $pivot = $this->pivot->where($this->localKey, $this->parent->$pk)->where($this->foreignKey, $id)->find(); + + return $pivot ?: false; + } + /** * 解除关联的一个中间表数据 * @access public diff --git a/thinkphp/library/think/model/relation/HasMany.php b/thinkphp/library/think/model/relation/HasMany.php index cfcf2a9..c4b31af 100755 --- a/thinkphp/library/think/model/relation/HasMany.php +++ b/thinkphp/library/think/model/relation/HasMany.php @@ -152,12 +152,16 @@ class HasMany extends Relation * 创建关联统计子查询 * @access public * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 * @return string */ - public function getRelationCountQuery($closure) + public function getRelationCountQuery($closure, &$name = null) { if ($closure) { - call_user_func_array($closure, [ & $this->query]); + $return = call_user_func_array($closure, [ & $this->query]); + if ($return && is_string($return)) { + $name = $return; + } } $localKey = $this->localKey ?: $this->parent->getPk(); return $this->query->whereExp($this->foreignKey, '=' . $this->parent->getTable() . '.' . $localKey)->fetchSql()->count(); @@ -197,14 +201,26 @@ class HasMany extends Relation * @return Model|false */ public function save($data) + { + $model = $this->make($data); + return $model->save($data) ? $model : false; + } + + /** + * 创建关联对象实例 + * @param array $data + * @return Model + */ + public function make($data = []) { if ($data instanceof Model) { $data = $data->getData(); } + // 保存关联表数据 - $model = new $this->model; $data[$this->foreignKey] = $this->parent->{$this->localKey}; - return $model->save($data) ? $model : false; + + return new $this->model($data); } /** diff --git a/thinkphp/library/think/model/relation/HasManyThrough.php b/thinkphp/library/think/model/relation/HasManyThrough.php index b7b3333..3a9a548 100755 --- a/thinkphp/library/think/model/relation/HasManyThrough.php +++ b/thinkphp/library/think/model/relation/HasManyThrough.php @@ -120,6 +120,18 @@ class HasManyThrough extends Relation public function relationCount($result, $closure) {} + /** + * 创建关联统计子查询 + * @access public + * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 + * @return string + */ + public function getRelationCountQuery($closure, &$name = null) + { + throw new Exception('relation not support: withCount'); + } + /** * 执行基础查询(进执行一次) * @access protected diff --git a/thinkphp/library/think/model/relation/MorphMany.php b/thinkphp/library/think/model/relation/MorphMany.php index 8945042..941ebe8 100755 --- a/thinkphp/library/think/model/relation/MorphMany.php +++ b/thinkphp/library/think/model/relation/MorphMany.php @@ -188,15 +188,19 @@ class MorphMany extends Relation } /** - * 获取关联统计子查询 + * 创建关联统计子查询 * @access public * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 * @return string */ - public function getRelationCountQuery($closure) + public function getRelationCountQuery($closure, &$name = null) { if ($closure) { - call_user_func_array($closure, [ & $this->query]); + $return = call_user_func_array($closure, [ & $this->query]); + if ($return && is_string($return)) { + $name = $return; + } } return $this->query->where([ @@ -240,17 +244,30 @@ class MorphMany extends Relation * @return Model|false */ public function save($data) + { + $model = $this->make($data); + + return $model->save($data) ? $model : false; + } + + /** + * 创建关联对象实例 + * @param array $data + * @return Model + */ + public function make($data = []) { if ($data instanceof Model) { $data = $data->getData(); } + // 保存关联表数据 $pk = $this->parent->getPk(); - $model = new $this->model; $data[$this->morphKey] = $this->parent->$pk; $data[$this->morphType] = $this->type; - return $model->save($data) ? $model : false; + + return new $this->model($data); } /** diff --git a/thinkphp/library/think/model/relation/MorphOne.php b/thinkphp/library/think/model/relation/MorphOne.php index 2337599..1f4bffd 100755 --- a/thinkphp/library/think/model/relation/MorphOne.php +++ b/thinkphp/library/think/model/relation/MorphOne.php @@ -81,8 +81,8 @@ class MorphOne extends Relation /** * 根据关联条件查询当前模型 * @access public - * @param mixed $where 查询条件(数组或者闭包) - * @param mixed $fields 字段 + * @param mixed $where 查询条件(数组或者闭包) + * @param mixed $fields 字段 * @return Query */ public function hasWhere($where = [], $fields = null) @@ -198,6 +198,17 @@ class MorphOne extends Relation * @return Model|false */ public function save($data) + { + $model = $this->make($data); + return $model->save() ? $model : false; + } + + /** + * 创建关联对象实例 + * @param array $data + * @return Model + */ + public function make($data = []) { if ($data instanceof Model) { $data = $data->getData(); @@ -205,10 +216,10 @@ class MorphOne extends Relation // 保存关联表数据 $pk = $this->parent->getPk(); - $model = new $this->model; $data[$this->morphKey] = $this->parent->$pk; $data[$this->morphType] = $this->type; - return $model->save($data) ? $model : false; + + return new $this->model($data); } /** @@ -227,4 +238,15 @@ class MorphOne extends Relation } } + /** + * 创建关联统计子查询 + * @access public + * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 + * @return string + */ + public function getRelationCountQuery($closure, &$name = null) + { + throw new Exception('relation not support: withCount'); + } } diff --git a/thinkphp/library/think/model/relation/MorphTo.php b/thinkphp/library/think/model/relation/MorphTo.php index 504130a..7d45265 100755 --- a/thinkphp/library/think/model/relation/MorphTo.php +++ b/thinkphp/library/think/model/relation/MorphTo.php @@ -105,7 +105,7 @@ class MorphTo extends Relation /** * 解析模型的完整命名空间 - * @access public + * @access protected * @param string $model 模型名(或者完整类名) * @return string */ @@ -285,4 +285,15 @@ class MorphTo extends Relation return $this->parent->setRelation($this->relation, null); } + /** + * 创建关联统计子查询 + * @access public + * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 + * @return string + */ + public function getRelationCountQuery($closure, &$name = null) + { + throw new Exception('relation not support: withCount'); + } } diff --git a/thinkphp/library/think/model/relation/OneToOne.php b/thinkphp/library/think/model/relation/OneToOne.php index dd8595c..353ce21 100755 --- a/thinkphp/library/think/model/relation/OneToOne.php +++ b/thinkphp/library/think/model/relation/OneToOne.php @@ -323,4 +323,15 @@ abstract class OneToOne extends Relation return $data; } + /** + * 创建关联统计子查询 + * @access public + * @param \Closure $closure 闭包 + * @param string $name 统计数据别名 + * @return string + */ + public function getRelationCountQuery($closure, &$name = null) + { + throw new Exception('relation not support: withCount'); + } } diff --git a/thinkphp/library/traits/model/SoftDelete.php b/thinkphp/library/traits/model/SoftDelete.php index 4c8a6b8..70f31ba 100755 --- a/thinkphp/library/traits/model/SoftDelete.php +++ b/thinkphp/library/traits/model/SoftDelete.php @@ -2,6 +2,7 @@ namespace traits\model; +use think\Collection; use think\db\Query; use think\Model; @@ -111,7 +112,7 @@ trait SoftDelete } // 包含软删除数据 - $query = self::withTrashed(); + $query = (new static())->db(false); if (is_array($data) && key($data) !== 0) { $query->where($data); $data = null;