diff --git a/application/admin/controller/Content.php b/application/admin/controller/Content.php index fb3931c1..4d01f6ea 100644 --- a/application/admin/controller/Content.php +++ b/application/admin/controller/Content.php @@ -26,7 +26,7 @@ class Content extends Admin { } else { $this->modelInfo = $list[$model_id]; if ($this->modelInfo['extend'] > 1) { - $this->model = model($this->modelInfo['name']); + $this->model = model('Content')->extend($this->modelInfo['name']); } else { $this->model = model('Document')->extend($this->modelInfo['name']); } @@ -55,9 +55,7 @@ class Content extends Admin { unset($map['model_id']); } - $list = $this->model->where($map)->order($order)->paginate(15, false, array( - 'query' => $this->param, - )); + $list = $this->model->lists($map, $order); $data = array( 'grid' => $grid_list, diff --git a/application/admin/view/content/index.html b/application/admin/view/content/index.html index e2a8ebc9..4c3c58b2 100644 --- a/application/admin/view/content/index.html +++ b/application/admin/view/content/index.html @@ -66,20 +66,20 @@ {if isset($item['is_top'])} {if $item['is_top']} - 取消置顶 + 取消置顶 {else/} - 置顶 + 置顶 {/if} {/if} {if isset($item['status'])} {if $item['status']} - 取消审核 + 取消审核 {else/} - 审核 + 审核 {/if} {/if} - 编辑 - 删除 + 编辑 + 删除 {/volist} diff --git a/application/common/behavior/InitHook.php b/application/common/behavior/InitHook.php index a2151981..f9a08e5a 100644 --- a/application/common/behavior/InitHook.php +++ b/application/common/behavior/InitHook.php @@ -66,13 +66,13 @@ class InitHook { $route[$value['name'] . "/index"] = "index/content/index?model=" . $value['name']; $route[$value['name'] . "/list/:id"] = "index/content/lists?model=" . $value['name']; $route[$value['name'] . "/detail/:id"] = "index/content/detail?model_id=" . $value['id']; - $route["/list/:id"] = "index/content/category"; $route["user/" . $value['name'] . "/index"] = "user/content/index?model_id=" . $value['id']; $route["user/" . $value['name'] . "/add"] = "user/content/add?model_id=" . $value['id']; $route["user/" . $value['name'] . "/edit"] = "user/content/edit?model_id=" . $value['id']; $route["user/" . $value['name'] . "/del"] = "user/content/del?model_id=" . $value['id']; $route["user/" . $value['name'] . "/status"] = "user/content/status?model_id=" . $value['id']; } + $route["list/:id"] = "index/content/category"; \think\Route::rule($route); } } \ No newline at end of file diff --git a/application/common/controller/Admin.php b/application/common/controller/Admin.php index 0ce2edd3..d31447d2 100644 --- a/application/common/controller/Admin.php +++ b/application/common/controller/Admin.php @@ -148,7 +148,7 @@ class Admin extends Base { $pid = db('menu')->where("pid !=0 AND url like '%{$hover_url}%'")->value('pid'); $id = db('menu')->where("pid = 0 AND url like '%{$hover_url}%'")->value('id'); $pid = $pid ? $pid : $id; - if ($hover_url == 'admin/content' || $hover_url == 'admin/attribute') { + if (strtolower($hover_url) == 'admin/content' || strtolower($hover_url) == 'admin/attribute') { //内容管理菜单 $pid = db('menu')->where("pid =0 AND url like '%admin/category%'")->value('id'); } diff --git a/application/common/model/Base.php b/application/common/model/Base.php index 372d7a02..40050a1c 100644 --- a/application/common/model/Base.php +++ b/application/common/model/Base.php @@ -14,11 +14,17 @@ namespace app\common\model; */ class Base extends \think\Model{ + protected $param; protected $type = array( 'id' => 'integer', 'cover_id' => 'integer', ); + public function initialize(){ + parent::initialize(); + $this->param = \think\Request::instance()->param(); + } + /** * 数据修改 * @return [bool] [是否成功] diff --git a/application/common/model/Content.php b/application/common/model/Content.php index 78175911..87d71579 100644 --- a/application/common/model/Content.php +++ b/application/common/model/Content.php @@ -14,11 +14,11 @@ namespace app\common\model; */ class Content extends Base{ - //protected $name = "page"; + protected $dao; protected $auto = array("update_time"); protected $insert = array("create_time"); - + protected $type = array( 'id' => 'integer', 'cover_id' => 'integer', @@ -37,27 +37,59 @@ class Content extends Base{ } public function extend($name){ - $this->name = $name; + $this->dao = db($name); return $this; } - public function detail($id){ + public function lists($map, $order){ + $list = $this->dao->where($map)->order($order)->paginate(15, false, array( + 'query' => $this->param, + )); + return $list; + } + + public function detail($id, $map = array()){ $map['id'] = $id; - $this->data = $this->db()->where($map)->find(); + $this->data = $this->dao->where($map)->find(); return $this->data; } + public function del($map){ + return $this->dao->where($map)->delete(); + } + public function change(){ - $data = input('post.'); - if ($data['id']) { - $result = $this->save($data,array('id'=>$data['id'])); + $data = $this->param; + if (isset($data['id']) && $data['id']) { + $where['id'] = $data['id']; + } + 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->autoCompleteData($this->auto); + + // 自动写入更新时间 + if ($this->autoWriteTimestamp && $this->updateTime) { + $this->setAttr($this->updateTime, null); + } + + if ($this->isUpdate) { + $result = $this->dao->update($this->data, $where); }else{ - $result = $this->save($data); + $result = $this->dao->insert($this->data); } return $result; } - - public function del($map){ - return $this->where($map)->delete(); - } } \ No newline at end of file diff --git a/application/common/model/Document.php b/application/common/model/Document.php index 2e347184..89e28169 100644 --- a/application/common/model/Document.php +++ b/application/common/model/Document.php @@ -12,7 +12,7 @@ namespace app\common\model; /** * 设置模型 */ -class Document extends \think\Model{ +class Document extends Base{ protected $fk = 'doc_id'; protected $pk = 'id'; @@ -72,9 +72,18 @@ class Document extends \think\Model{ public function extend($name){ $name = strtoupper($name); $this->join('__DOCUMENT_' . $name . '__', $this->fk . '=' . $this->pk, 'LEFT'); + $this->dao = $this->db()->alias('d') + ->join('__DOCUMENT_' . $name . '__ dc', 'dc.' . $this->fk . '= d.' . $this->pk, 'RIGHT'); return $this; } + public function lists($map, $order){ + $list = $this->dao->where($map)->order($order)->paginate(15, false, array( + 'query' => $this->param, + )); + return $list; + } + public function change(){ /* 获取数据对象 */ $data = \think\Request::instance()->post(); diff --git a/core/base.php b/core/base.php index 1184dc51..5bd1b405 100644 --- a/core/base.php +++ b/core/base.php @@ -9,7 +9,7 @@ // | Author: liu21st // +---------------------------------------------------------------------- -define('THINK_VERSION', '5.0.2dev'); +define('THINK_VERSION', '5.0.3'); define('THINK_START_TIME', microtime(true)); define('THINK_START_MEM', memory_get_usage()); define('EXT', '.php'); diff --git a/core/convention.php b/core/convention.php index f7486a48..8eb30f43 100644 --- a/core/convention.php +++ b/core/convention.php @@ -58,6 +58,8 @@ return [ 'default_validate' => '', // 默认的空控制器名 'empty_controller' => 'Error', + // 操作方法前缀 + 'use_action_prefix' => false, // 操作方法后缀 'action_suffix' => '', // 自动搜索控制器 @@ -83,6 +85,8 @@ return [ 'url_route_on' => true, // 路由配置文件(支持配置多个) 'route_config_file' => ['route'], + // 路由使用完整匹配 + 'route_complete_match' => false, // 是否强制使用路由 'url_route_must' => false, // 域名部署 @@ -99,6 +103,10 @@ return [ 'var_ajax' => '_ajax', // 表单pjax伪装变量 'var_pjax' => '_pjax', + // 是否开启请求缓存 true自动缓存 支持设置请求缓存规则 + 'request_cache' => false, + // 请求缓存有效期 + 'request_cache_expire' => null, // +---------------------------------------------------------------------- // | 模板设置 diff --git a/core/helper.php b/core/helper.php index 6ab2cb34..02d8761a 100644 --- a/core/helper.php +++ b/core/helper.php @@ -117,7 +117,7 @@ if (!function_exists('input')) { * @param string $filter 过滤方法 * @return mixed */ - function input($key = '', $default = null, $filter = null) + function input($key = '', $default = null, $filter = '') { if (0 === strpos($key, '?')) { $key = substr($key, 1); @@ -125,10 +125,9 @@ if (!function_exists('input')) { } if ($pos = strpos($key, '.')) { // 指定参数来源 - $method = substr($key, 0, $pos); - if (in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) { - $key = substr($key, $pos + 1); - } else { + list($method, $key) = explode('.', $key, 2); + if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) { + $key = $method . '.' . $key; $method = 'param'; } } else { @@ -298,7 +297,7 @@ if (!function_exists('session')) { Session::init($name); } elseif (is_null($name)) { // 清除 - Session::clear($value); + Session::clear('' === $value ? null : $value); } elseif ('' === $value) { // 判断或获取 return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix); @@ -359,12 +358,17 @@ if (!function_exists('cache')) { // 缓存初始化 return Cache::connect($name); } - if ('' === $value) { + if (is_null($name)) { + return Cache::clear($value); + } elseif ('' === $value) { // 获取缓存 return 0 === strpos($name, '?') ? Cache::has(substr($name, 1)) : Cache::get($name); } elseif (is_null($value)) { // 删除缓存 return Cache::rm($name); + } elseif (0 === strpos($name, '?') && '' !== $value) { + $expire = is_numeric($options) ? $options : null; + return Cache::remember(substr($name, 1), $value, $expire); } else { // 缓存数据 if (is_array($options)) { diff --git a/core/library/think/App.php b/core/library/think/App.php index 67aac096..4eddc7cd 100644 --- a/core/library/think/App.php +++ b/core/library/think/App.php @@ -16,6 +16,7 @@ use think\Env; use think\Exception; use think\exception\HttpException; use think\exception\HttpResponseException; +use think\exception\RouteNotFoundException; use think\Hook; use think\Lang; use think\Loader; @@ -126,6 +127,8 @@ class App // 监听app_begin Hook::listen('app_begin', $dispatch); + // 请求缓存检查 + $request->cache($config['request_cache'], $config['request_cache_expire']); switch ($dispatch['type']) { case 'redirect': @@ -280,7 +283,14 @@ class App if ($bind instanceof $className) { $args[] = $bind; } else { - $args[] = method_exists($className, 'instance') ? $className::instance() : new $className(); + if (method_exists($className, 'invoke')) { + $method = new \ReflectionMethod($className, 'invoke'); + if ($method->isPublic() && $method->isStatic()) { + $args[] = $className::invoke(Request::instance()); + continue; + } + } + $args[] = method_exists($className, 'instance') ? $className::instance() : new $className; } } elseif (1 == $type && !empty($vars)) { $args[] = array_shift($vars); @@ -362,34 +372,29 @@ class App // 监听module_init Hook::listen('module_init', $request); - try { - $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); - if (is_null($instance)) { - throw new HttpException(404, 'controller not exists:' . Loader::parseName($controller, 1)); - } - // 获取当前操作名 - $action = $actionName . $config['action_suffix']; - if (!preg_match('/^[A-Za-z](\w)*$/', $action)) { - // 非法操作 - throw new \ReflectionException('illegal action name:' . $actionName); - } + $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); + if (is_null($instance)) { + throw new HttpException(404, 'controller not exists:' . Loader::parseName($controller, 1)); + } + // 获取当前操作名 + $action = $actionName . $config['action_suffix']; + $vars = []; + if (is_callable([$instance, $action])) { // 执行操作方法 $call = [$instance, $action]; - Hook::listen('action_begin', $call); - - $data = self::invokeMethod($call); - } catch (\ReflectionException $e) { + } elseif (is_callable([$instance, '_empty'])) { + // 空操作 + $call = [$instance, '_empty']; + $vars = [$action]; + } else { // 操作不存在 - if (method_exists($instance, '_empty')) { - $reflect = new \ReflectionMethod($instance, '_empty'); - $data = $reflect->invokeArgs($instance, [$action]); - self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info'); - } else { - throw new HttpException(404, 'method not exists:' . (new \ReflectionClass($instance))->getName() . '->' . $action); - } + throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()'); } - return $data; + + Hook::listen('action_begin', $call); + + return self::invokeMethod($call, $vars); } /** @@ -545,7 +550,7 @@ class App $must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must']; if ($must && false === $result) { // 路由无效 - throw new HttpException(404, 'Route Not Found'); + throw new RouteNotFoundException(); } } if (false === $result) { diff --git a/core/library/think/Cache.php b/core/library/think/Cache.php index a5ac0b32..208190be 100644 --- a/core/library/think/Cache.php +++ b/core/library/think/Cache.php @@ -185,6 +185,35 @@ class Cache return self::$handler->clear($tag); } + /** + * 读取缓存并删除 + * @access public + * @param string $name 缓存变量名 + * @return mixed + */ + public static function pull($name) + { + self::init(); + self::$readTimes++; + self::$writeTimes++; + return self::$handler->pull($name); + } + + /** + * 如果不存在则写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param int $expire 有效时间 0为永久 + * @return mixed + */ + public static function remember($name, $value, $expire = null) + { + self::init(); + self::$readTimes++; + return self::$handler->remember($name, $value, $expire); + } + /** * 缓存标签 * @access public diff --git a/core/library/think/Config.php b/core/library/think/Config.php index d7c3dc56..fb5340d8 100644 --- a/core/library/think/Config.php +++ b/core/library/think/Config.php @@ -59,6 +59,7 @@ class Config self::$config[$range] = []; } if (is_file($file)) { + $name = strtolower($name); $type = pathinfo($file, PATHINFO_EXTENSION); if ('php' == $type) { return self::set(include $file, $name, $range); diff --git a/core/library/think/Controller.php b/core/library/think/Controller.php index a889e4d9..fe4efae2 100644 --- a/core/library/think/Controller.php +++ b/core/library/think/Controller.php @@ -20,9 +20,13 @@ class Controller { use \traits\controller\Jump; - // 视图类实例 + /** + * @var \think\View 视图类实例 + */ protected $view; - // Request实例 + /** + * @var \think\Request Request实例 + */ protected $request; // 验证失败是否抛出异常 protected $failException = false; diff --git a/core/library/think/Db.php b/core/library/think/Db.php index b00aee61..c67cba6f 100644 --- a/core/library/think/Db.php +++ b/core/library/think/Db.php @@ -42,6 +42,9 @@ use think\paginator\Collection as PaginatorCollection; * @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行 * @method PaginatorCollection paginate(integer $listRows = 15, mixed $simple = false, array $config = []) static 分页查询 * @method mixed transaction(callable $callback) static 执行数据库事务 + * @method void startTrans() static 启动事务 + * @method void commit() static 用于非自动提交状态下面的查询提交 + * @method void rollback() static 事务回滚 * @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句 */ class Db diff --git a/core/library/think/File.php b/core/library/think/File.php index 43f38575..60a16417 100644 --- a/core/library/think/File.php +++ b/core/library/think/File.php @@ -39,7 +39,7 @@ class File extends SplFileObject public function __construct($filename, $mode = 'r') { parent::__construct($filename, $mode); - $this->filename = $this->getRealPath(); + $this->filename = $this->getRealPath() ?: $this->getPathname(); } /** diff --git a/core/library/think/Loader.php b/core/library/think/Loader.php index cfa0a217..9f54ad3a 100644 --- a/core/library/think/Loader.php +++ b/core/library/think/Loader.php @@ -365,8 +365,9 @@ class Loader */ public static function model($name = '', $layer = 'model', $appendSuffix = false, $common = 'common') { - if (isset(self::$instance[$name . $layer])) { - return self::$instance[$name . $layer]; + $guid = $name . $layer; + if (isset(self::$instance[$guid])) { + return self::$instance[$guid]; } if (strpos($name, '/')) { list($module, $name) = explode('/', $name, 2); @@ -384,7 +385,7 @@ class Loader throw new ClassNotFoundException('class not exists:' . $class, $class); } } - self::$instance[$name . $layer] = $model; + self::$instance[$guid] = $model; return $model; } @@ -427,9 +428,9 @@ class Loader if (empty($name)) { return new Validate; } - - if (isset(self::$instance[$name . $layer])) { - return self::$instance[$name . $layer]; + $guid = $name . $layer; + if (isset(self::$instance[$guid])) { + return self::$instance[$guid]; } if (strpos($name, '/')) { list($module, $name) = explode('/', $name); @@ -447,7 +448,7 @@ class Loader throw new ClassNotFoundException('class not exists:' . $class, $class); } } - self::$instance[$name . $layer] = $validate; + self::$instance[$guid] = $validate; return $validate; } diff --git a/core/library/think/Model.php b/core/library/think/Model.php index a96c7d6e..181ed8e9 100644 --- a/core/library/think/Model.php +++ b/core/library/think/Model.php @@ -101,6 +101,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess protected $failException = false; // 全局查询范围 protected $useGlobalScope = true; + // 是否采用批量验证 + protected $batchValidate = false; /** * 初始化过的模型. @@ -649,7 +651,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess if (false === $this->trigger('before_write', $this)) { return false; } - + $pk = $this->getPk(); if ($this->isUpdate) { // 自动更新 $this->autoCompleteData($this->update); @@ -680,7 +682,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $where = $this->updateWhere; } - $pk = $this->getPk(); if (is_string($pk) && isset($data[$pk])) { if (!isset($where[$pk])) { unset($where); @@ -710,10 +711,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $result = $this->db()->insert($this->data); // 获取自动增长主键 - if ($result) { + if ($result && is_string($pk) && !isset($this->data[$pk])) { $insertId = $this->db()->getLastInsID($sequence); - $pk = $this->getPk(); - if (is_string($pk) && $insertId) { + if ($insertId) { $this->data[$pk] = $insertId; } } @@ -743,7 +743,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 数据批量验证 $validate = $this->validate; foreach ($dataSet as $data) { - if (!$this->validate($validate)->validateData($data)) { + if (!$this->validateData($data, $validate)) { return false; } } @@ -759,9 +759,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess } foreach ($dataSet as $key => $data) { if (!empty($auto) && isset($data[$pk])) { - $result[$key] = self::update($data); + $result[$key] = self::update($data, [], $this->field); } else { - $result[$key] = self::create($data); + $result[$key] = self::create($data, $this->field); } } $db->commit(); @@ -856,9 +856,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess * @access public * @param array|string|bool $rule 验证规则 true表示自动读取验证器类 * @param array $msg 提示信息 + * @param bool $batch 批量验证 * @return $this */ - public function validate($rule = true, $msg = []) + public function validate($rule = true, $msg = [], $batch = false) { if (is_array($rule)) { $this->validate = [ @@ -868,6 +869,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess } else { $this->validate = true === $rule ? $this->name : $rule; } + $this->batchValidate = $batch; return $this; } @@ -887,12 +889,15 @@ abstract class Model implements \JsonSerializable, \ArrayAccess * 自动验证数据 * @access protected * @param array $data 验证数据 + * @param mixed $rule 验证规则 + * @param bool $batch 批量验证 * @return bool */ - protected function validateData($data) + protected function validateData($data, $rule = null, $batch = null) { - if (!empty($this->validate)) { - $info = $this->validate; + $info = is_null($rule) ? $this->validate : $rule; + + if (!empty($info)) { if (is_array($info)) { $validate = Loader::validate(); $validate->rule($info['rule']); @@ -907,7 +912,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess $validate->scene($scene); } } - if (!$validate->check($data)) { + $batch = is_null($batch) ? $this->batchValidate : $batch; + + if (!$validate->batch($batch)->check($data)) { $this->error = $validate->getError(); if ($this->failException) { throw new ValidateException($this->error); @@ -972,12 +979,16 @@ abstract class Model implements \JsonSerializable, \ArrayAccess /** * 写入数据 * @access public - * @param array $data 数据数组 + * @param array $data 数据数组 + * @param array|true $field 允许字段 * @return $this */ - public static function create($data = []) + public static function create($data = [], $field = null) { $model = new static(); + if (!empty($field)) { + $model->allowField($field); + } $model->isUpdate(false)->save($data, []); return $model; } @@ -985,13 +996,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess /** * 更新数据 * @access public - * @param array $data 数据数组 - * @param array $where 更新条件 + * @param array $data 数据数组 + * @param array $where 更新条件 + * @param array|true $field 允许字段 * @return $this */ - public static function update($data = [], $where = []) + public static function update($data = [], $where = [], $field = null) { - $model = new static(); + $model = new static(); + if (!empty($field)) { + $model->allowField($field); + } $result = $model->isUpdate(true)->save($data, $where); return $model; } @@ -1358,19 +1373,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess public static function __callStatic($method, $params) { - $query = self::getDb(); + $query = (new static())->db(); return call_user_func_array([$query, $method], $params); } - protected static function getDb() - { - $model = get_called_class(); - if (!isset(self::$links[$model])) { - self::$links[$model] = (new static())->db(); - } - return self::$links[$model]; - } - /** * 修改器 设置数据对象的值 * @access public diff --git a/core/library/think/Request.php b/core/library/think/Request.php index 75f2b9ef..45b65423 100644 --- a/core/library/think/Request.php +++ b/core/library/think/Request.php @@ -121,6 +121,8 @@ class Request protected $input; // 请求缓存 protected $cache; + // 缓存是否检查 + protected $isCheckCache; /** * 架构函数 @@ -248,7 +250,7 @@ class Request $options['baseUrl'] = $info['path']; $options['pathinfo'] = '/' == $info['path'] ? '/' : ltrim($info['path'], '/'); $options['method'] = $server['REQUEST_METHOD']; - $options['domain'] = $info['scheme'] . '://' . $server['HTTP_HOST']; + $options['domain'] = isset($info['scheme']) ? $info['scheme'] . '://' . $server['HTTP_HOST'] : ''; $options['content'] = $content; self::$instance = new self($options); return self::$instance; @@ -607,7 +609,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function param($name = '', $default = null, $filter = null) + public function param($name = '', $default = null, $filter = '') { if (empty($this->param)) { $method = $this->method(true); @@ -644,7 +646,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function route($name = '', $default = null, $filter = null) + public function route($name = '', $default = null, $filter = '') { if (is_array($name)) { $this->param = []; @@ -661,7 +663,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function get($name = '', $default = null, $filter = null) + public function get($name = '', $default = null, $filter = '') { if (empty($this->get)) { $this->get = $_GET; @@ -681,7 +683,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function post($name = '', $default = null, $filter = null) + public function post($name = '', $default = null, $filter = '') { if (empty($this->post)) { $this->post = $_POST; @@ -701,7 +703,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function put($name = '', $default = null, $filter = null) + public function put($name = '', $default = null, $filter = '') { if (is_null($this->put)) { $content = $this->input; @@ -727,7 +729,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function delete($name = '', $default = null, $filter = null) + public function delete($name = '', $default = null, $filter = '') { return $this->put($name, $default, $filter); } @@ -740,7 +742,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function patch($name = '', $default = null, $filter = null) + public function patch($name = '', $default = null, $filter = '') { return $this->put($name, $default, $filter); } @@ -752,7 +754,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function request($name = '', $default = null, $filter = null) + public function request($name = '', $default = null, $filter = '') { if (empty($this->request)) { $this->request = $_REQUEST; @@ -772,7 +774,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function session($name = '', $default = null, $filter = null) + public function session($name = '', $default = null, $filter = '') { if (empty($this->session)) { $this->session = Session::get(); @@ -791,7 +793,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function cookie($name = '', $default = null, $filter = null) + public function cookie($name = '', $default = null, $filter = '') { if (empty($this->cookie)) { $this->cookie = $_COOKIE; @@ -810,7 +812,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function server($name = '', $default = null, $filter = null) + public function server($name = '', $default = null, $filter = '') { if (empty($this->server)) { $this->server = $_SERVER; @@ -888,7 +890,7 @@ class Request * @param string|array $filter 过滤方法 * @return mixed */ - public function env($name = '', $default = null, $filter = null) + public function env($name = '', $default = null, $filter = '') { if (empty($this->env)) { $this->env = $_ENV; @@ -947,7 +949,7 @@ class Request * @param string|array $filter 过滤函数 * @return mixed */ - public function input($data = [], $name = '', $default = null, $filter = null) + public function input($data = [], $name = '', $default = null, $filter = '') { if (false === $name) { // 获取原始数据 @@ -976,13 +978,17 @@ class Request } // 解析过滤器 - $filter = $filter ?: $this->filter; - - if (is_string($filter)) { - $filter = explode(',', $filter); + if (is_null($filter)) { + $filter = []; } else { - $filter = (array) $filter; + $filter = $filter ?: $this->filter; + if (is_string($filter)) { + $filter = explode(',', $filter); + } else { + $filter = (array) $filter; + } } + $filter[] = $default; if (is_array($data)) { array_walk_recursive($data, [$this, 'filterValue'], $filter); @@ -1241,8 +1247,7 @@ class Request if (false !== $pos) { unset($arr[$pos]); } - - $ip = trim($arr[0]); + $ip = trim(current($arr)); } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { $ip = $_SERVER['HTTP_CLIENT_IP']; } elseif (isset($_SERVER['REMOTE_ADDR'])) { @@ -1370,7 +1375,7 @@ class Request * 设置或者获取当前的模块名 * @access public * @param string $module 模块名 - * @return string|$this + * @return string|Request */ public function module($module = null) { @@ -1386,7 +1391,7 @@ class Request * 设置或者获取当前的控制器名 * @access public * @param string $controller 控制器名 - * @return string|$this + * @return string|Request */ public function controller($controller = null) { @@ -1402,7 +1407,7 @@ class Request * 设置或者获取当前的操作名 * @access public * @param string $action 操作名 - * @return string + * @return string|Request */ public function action($action = null) { @@ -1418,7 +1423,7 @@ class Request * 设置或者获取当前的语言 * @access public * @param string $lang 语言名 - * @return string + * @return string|Request */ public function langset($lang = null) { @@ -1472,15 +1477,34 @@ class Request } /** - * 读取或者设置缓存 + * 设置当前地址的请求缓存 * @access public * @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id * @param mixed $expire 缓存有效期 - * @return mixed + * @return void */ public function cache($key, $expire = null) { - if ($this->isGet()) { + if (false !== $key && $this->isGet() && !$this->isCheckCache) { + // 标记请求缓存检查 + $this->isCheckCache = true; + if (false === $expire) { + // 关闭当前缓存 + return; + } + if ($key instanceof \Closure) { + $key = call_user_func_array($key, [$this]); + } elseif (true === $key) { + // 自动缓存功能 + $key = '__URL__'; + } elseif (strpos($key, '|')) { + list($key, $fun) = explode('|', $key); + } + // 特殊规则替换 + if (false !== strpos($key, '__')) { + $key = str_replace(['__MODULE__', '__CONTROLLER__', '__ACTION__', '__URL__'], [$this->module, $this->controller, $this->action, md5($this->url())], $key); + } + if (false !== strpos($key, ':')) { $param = $this->param(); foreach ($param as $item => $val) { @@ -1488,9 +1512,6 @@ class Request $key = str_replace(':' . $item, $val, $key); } } - } elseif ('__URL__' == $key) { - // 当前URL地址作为缓存标识 - $key = md5($this->url()); } elseif (strpos($key, ']')) { if ('[' . $this->ext() . ']' == $key) { // 缓存某个后缀的请求 @@ -1499,6 +1520,9 @@ class Request return; } } + if (isset($fun)) { + $key = $fun($key); + } if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) { // 读取缓存 @@ -1515,7 +1539,7 @@ class Request } /** - * 读取缓存设置 + * 读取请求缓存设置 * @access public * @return array */ diff --git a/core/library/think/Response.php b/core/library/think/Response.php index 8b62e419..a202ce76 100644 --- a/core/library/think/Response.php +++ b/core/library/think/Response.php @@ -130,6 +130,9 @@ class Response // 监听response_end Hook::listen('response_end', $this); + + // 清空当次请求有效的数据 + Session::flush(); } /** diff --git a/core/library/think/Route.php b/core/library/think/Route.php index 8ecbcb7e..96e47895 100644 --- a/core/library/think/Route.php +++ b/core/library/think/Route.php @@ -24,13 +24,13 @@ class Route { // 路由规则 private static $rules = [ - 'GET' => [], - 'POST' => [], - 'PUT' => [], - 'DELETE' => [], - 'PATCH' => [], - 'HEAD' => [], - 'OPTIONS' => [], + 'get' => [], + 'post' => [], + 'put' => [], + 'delete' => [], + 'patch' => [], + 'head' => [], + 'options' => [], '*' => [], 'alias' => [], 'domain' => [], @@ -40,21 +40,22 @@ class Route // REST路由操作方法定义 private static $rest = [ - 'index' => ['GET', '', 'index'], - 'create' => ['GET', '/create', 'create'], - 'edit' => ['GET', '/:id/edit', 'edit'], - 'read' => ['GET', '/:id', 'read'], - 'save' => ['POST', '', 'save'], - 'update' => ['PUT', '/:id', 'update'], - 'delete' => ['DELETE', '/:id', 'delete'], + 'index' => ['get', '', 'index'], + 'create' => ['get', '/create', 'create'], + 'edit' => ['get', '/:id/edit', 'edit'], + 'read' => ['get', '/:id', 'read'], + 'save' => ['post', '', 'save'], + 'update' => ['put', '/:id', 'update'], + 'delete' => ['delete', '/:id', 'delete'], ]; // 不同请求类型的方法前缀 private static $methodPrefix = [ - 'GET' => 'get', - 'POST' => 'post', - 'PUT' => 'put', - 'DELETE' => 'delete', + 'get' => 'get', + 'post' => 'post', + 'put' => 'put', + 'delete' => 'delete', + 'patch' => 'patch', ]; // 子域名 @@ -68,6 +69,8 @@ class Route private static $domainRule; // 当前域名 private static $domain; + // 当前路由执行过程中的参数 + private static $option = []; /** * 注册变量规则 @@ -126,7 +129,7 @@ class Route * 设置路由绑定 * @access public * @param mixed $bind 绑定信息 - * @param string $type 绑定类型 默认为module 支持 namespace class + * @param string $type 绑定类型 默认为module 支持 namespace class controller * @return mixed */ public static function bind($bind, $type = 'module') @@ -148,8 +151,9 @@ class Route } elseif ('' === $name) { return self::$rules['name']; } elseif (!is_null($value)) { - self::$rules['name'][$name][] = $value; + self::$rules['name'][strtolower($name)][] = $value; } else { + $name = strtolower($name); return isset(self::$rules['name'][$name]) ? self::$rules['name'][$name] : null; } } @@ -198,7 +202,7 @@ class Route unset($rule['__rest__']); } - self::registerRules($rule, strtoupper($type)); + self::registerRules($rule, strtolower($type)); } // 批量注册路由 @@ -241,7 +245,7 @@ class Route $pattern = array_merge(self::getGroup('pattern'), $pattern); } - $type = strtoupper($type); + $type = strtolower($type); if (strpos($type, '|')) { $option['method'] = $type; @@ -300,12 +304,12 @@ class Route $rule = substr($rule, 0, -1); } - if ('/' != $rule) { + if ('/' != $rule || $group) { $rule = trim($rule, '/'); } $vars = self::parseVar($rule); if (isset($name)) { - $key = $group ? $group . '/' . $rule : $rule; + $key = $group ? $group . ($rule ? '/' . $rule : '') : $rule; self::name($name, [$key, $vars, self::$domain]); } if ($group) { @@ -328,7 +332,7 @@ class Route } if ('*' == $type) { // 注册路由快捷方式 - foreach (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as $method) { + foreach (['get', 'post', 'put', 'delete', 'patch', 'head', 'options'] as $method) { if (self::$domain) { self::$rules['domain'][self::$domain][$method][$rule] = true; } else { @@ -339,6 +343,27 @@ class Route } } + /** + * 设置当前执行的参数信息 + * @access public + * @param array $options 参数信息 + * @return mixed + */ + protected static function setOption($options = []) + { + self::$option[] = $options; + } + + /** + * 获取当前执行的所有参数信息 + * @access public + * @return array + */ + public static function getOption() + { + return self::$option; + } + /** * 获取当前的分组信息 * @access public @@ -423,15 +448,16 @@ class Route $options['complete_match'] = true; $key = substr($key, 0, -1); } + $key = trim($key, '/'); $vars = self::parseVar($key); $item[] = ['rule' => $key, 'route' => $route, 'var' => $vars, 'option' => $options, 'pattern' => $patterns]; // 设置路由标识 - self::name($route, [$name . '/' . $key, $vars, self::$domain]); + self::name($route, [$name . ($key ? '/' . $key : ''), $vars, self::$domain]); } self::$rules['*'][$name] = ['rule' => $item, 'route' => '', 'var' => [], 'option' => $option, 'pattern' => $pattern]; } - foreach (['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'] as $method) { + foreach (['get', 'post', 'put', 'delete', 'patch', 'head', 'options'] as $method) { if (!isset(self::$rules[$method][$name])) { self::$rules[$method][$name] = true; } elseif (is_array(self::$rules[$method][$name])) { @@ -576,7 +602,8 @@ class Route } elseif (strpos($val[1], ':id') && isset($option['var'][$rule])) { $val[1] = str_replace(':id', ':' . $option['var'][$rule], $val[1]); } - $item = ltrim($rule . $val[1], '/'); + $item = ltrim($rule . $val[1], '/'); + $option['rest'] = $key; self::rule($item . '$', $route . '/' . $val[2], $val[0], $option, $pattern); } } @@ -625,9 +652,9 @@ class Route public static function setMethodPrefix($method, $prefix = '') { if (is_array($method)) { - self::$methodPrefix = array_merge(self::$methodPrefix, array_change_key_case($method, CASE_UPPER)); + self::$methodPrefix = array_merge(self::$methodPrefix, array_change_key_case($method)); } else { - self::$methodPrefix[strtoupper($method)] = $prefix; + self::$methodPrefix[strtolower($method)] = $prefix; } } @@ -635,7 +662,7 @@ class Route * rest方法定义和修改 * @access public * @param string $name 方法名称 - * @param array $resourece 资源 + * @param array $resource 资源 * @return void */ public static function rest($name, $resource = []) @@ -682,7 +709,7 @@ class Route if (is_array($rules)) { self::$rules = $rules; } elseif ($rules) { - return true === $rules ? self::$rules : self::$rules[$rules]; + return true === $rules ? self::$rules : self::$rules[strtolower($rules)]; } else { $rules = self::$rules; unset($rules['pattern'], $rules['alias'], $rules['domain'], $rules['name']); @@ -698,7 +725,7 @@ class Route * @param string $method 请求类型 * @return void */ - public static function checkDomain($request, &$currentRules, $method = 'GET') + public static function checkDomain($request, &$currentRules, $method = 'get') { // 域名规则 $rules = self::$rules['domain']; @@ -808,7 +835,7 @@ class Route return $result; } } - $method = $request->method(); + $method = strtolower($request->method()); // 获取当前请求类型的路由规则 $rules = self::$rules[$method]; // 检测域名部署 @@ -823,14 +850,16 @@ class Route if ('|' != $url) { $url = rtrim($url, '|'); } - if (isset($rules[$url])) { + $item = str_replace('|', '/', $url); + if (isset($rules[$item])) { // 静态路由规则检测 - $rule = $rules[$url]; + $rule = $rules[$item]; if (true === $rule) { - $rule = self::getRouteExpress($url); + $rule = self::getRouteExpress($item); } if (!empty($rule['route']) && self::checkOption($rule['option'], $request)) { - return self::parseRule($url, $rule['route'], $url, $rule['option']); + self::setOption($rule['option']); + return self::parseRule($item, $rule['route'], $url, $rule['option']); } } @@ -893,7 +922,7 @@ class Route if (is_string($str) && $str && 0 !== strpos(str_replace('|', '/', $url), $str)) { continue; } - + self::setOption($option); $result = self::checkRoute($request, $rule, $url, $depr, $key, $option); if (false !== $result) { return $result; @@ -908,6 +937,8 @@ class Route if ($group) { $rule = $group . ($rule ? '/' . ltrim($rule, '/') : ''); } + + self::setOption($option); if (isset($options['bind_model']) && isset($option['bind_model'])) { $option['bind_model'] = array_merge($options['bind_model'], $option['bind_model']); } @@ -994,6 +1025,9 @@ class Route case 'class': // 绑定到类 return self::bindToClass($url, $bind, $depr); + case 'controller': + // 绑定到控制器类 + return self::bindToController($url, $bind, $depr); case 'namespace': // 绑定到命名空间 return self::bindToNamespace($url, $bind, $depr); @@ -1038,7 +1072,7 @@ class Route if (!empty($array[2])) { self::parseUrlParams($array[2]); } - return ['type' => 'method', 'method' => [$namespace . '\\' . $class, $method]]; + return ['type' => 'method', 'method' => [$namespace . '\\' . Loader::parseName($class, 1), $method]]; } /** @@ -1088,12 +1122,16 @@ class Route */ private static function checkOption($option, $request) { - // 请求类型检测 if ((isset($option['method']) && is_string($option['method']) && false === stripos($option['method'], $request->method())) - || (isset($option['ext']) && false === stripos($option['ext'], $request->ext())) // 伪静态后缀检测 + || (isset($option['ajax']) && $option['ajax'] && !$request->isAjax()) // Ajax检测 + || (isset($option['ajax']) && !$option['ajax'] && $request->isAjax()) // 非Ajax检测 + || (isset($option['pjax']) && $option['pjax'] && !$request->isPjax()) // Pjax检测 + || (isset($option['pjax']) && !$option['pjax'] && $request->isPjax()) // 非Pjax检测 + || (isset($option['ext']) && false === stripos($option['ext'], $request->ext())) // 伪静态后缀检测 || (isset($option['deny_ext']) && false !== stripos($option['deny_ext'], $request->ext())) || (isset($option['domain']) && !in_array($option['domain'], [$_SERVER['HTTP_HOST'], self::$subDomain])) // 域名检测 - || (!empty($option['https']) && !$request->isSsl()) // https检测 + || (isset($option['https']) && $option['https'] && !$request->isSsl()) // https检测 + || (isset($option['https']) && !$option['https'] && $request->isSsl()) // https检测 || (!empty($option['before_behavior']) && false === Hook::exec($option['before_behavior'])) // 行为检测 || (!empty($option['callback']) && is_callable($option['callback']) && false === call_user_func($option['callback'])) // 自定义检测 ) { @@ -1161,8 +1199,9 @@ class Route { if (isset(self::$bind['module'])) { + $bind = str_replace('/', $depr, self::$bind['module']); // 如果有模块/控制器绑定 - $url = self::$bind['module'] . '/' . ltrim($url, '/'); + $url = $bind . ('.' != substr($bind, -1) ? $depr : '') . ltrim($url, $depr); } $url = str_replace($depr, '|', $url); list($path, $var) = self::parseUrlPath($url); @@ -1175,15 +1214,24 @@ class Route $dir = APP_PATH . ($module ? $module . DS : '') . Config::get('url_controller_layer'); $suffix = App::$suffix || Config::get('controller_suffix') ? ucfirst(Config::get('url_controller_layer')) : ''; $item = []; + $find = false; foreach ($path as $val) { - $item[] = array_shift($path); - if (is_file($dir . DS . $val . $suffix . EXT)) { + $item[] = $val; + $file = $dir . DS . str_replace('.', DS, $val) . $suffix . EXT; + $file = pathinfo($file, PATHINFO_DIRNAME) . DS . Loader::parseName(pathinfo($file, PATHINFO_FILENAME), 1) . EXT; + if (is_file($file)) { + $find = true; break; } else { $dir .= DS . $val; } } - $controller = implode('.', $item); + if ($find) { + $controller = implode('.', $item); + $path = array_slice($path, count($item)); + } else { + $controller = array_shift($path); + } } else { // 解析控制器 $controller = !empty($path) ? array_shift($path) : null; @@ -1194,8 +1242,15 @@ class Route self::parseUrlParams(empty($path) ? '' : implode('|', $path)); // 封装路由 $route = [$module, $controller, $action]; - if (isset(self::$rules['name'][implode($depr, $route)])) { - throw new HttpException(404, 'invalid request:' . $url); + // 检查地址是否被定义过路由 + $name = strtolower($module . '/' . Loader::parseName($controller, 1) . '/' . $action); + $name2 = ''; + if (empty($module) || isset($bind) && $module == $bind) { + $name2 = strtolower(Loader::parseName($controller, 1) . '/' . $action); + } + + if (isset(self::$rules['name'][$name]) || isset(self::$rules['name'][$name2])) { + throw new HttpException(404, 'invalid request:' . str_replace('|', $depr, $url)); } } return ['type' => 'module', 'module' => $route]; @@ -1285,9 +1340,16 @@ class Route if (!$optional && !isset($m1[$key])) { return false; } - if (isset($m1[$key]) && isset($pattern[$name]) && !preg_match('/^' . $pattern[$name] . '$/', $m1[$key])) { + if (isset($m1[$key]) && isset($pattern[$name])) { // 检查变量规则 - return false; + if ($pattern[$name] instanceof \Closure) { + $result = call_user_func_array($pattern[$name], [$m1[$key]]); + if (false === $result) { + return false; + } + } elseif (!preg_match('/^' . $pattern[$name] . '$/', $m1[$key])) { + return false; + } } $var[$name] = isset($m1[$key]) ? $m1[$key] : ''; } elseif (!isset($m1[$key]) || 0 !== strcasecmp($val, $m1[$key])) { @@ -1343,7 +1405,6 @@ class Route foreach ($matches as $key => $val) { if (false !== strpos($route, ':' . $key)) { $route = str_replace(':' . $key, $val, $route); - unset($matches[$key]); } } } @@ -1430,7 +1491,7 @@ class Route $result = self::parseModule($route); } // 开启请求缓存 - if ($request->isGet() && !empty($option['cache'])) { + if ($request->isGet() && isset($option['cache'])) { $cache = $option['cache']; if (is_array($cache)) { list($key, $expire) = $cache; diff --git a/core/library/think/Session.php b/core/library/think/Session.php index bc57f3cd..ab0bdfa5 100644 --- a/core/library/think/Session.php +++ b/core/library/think/Session.php @@ -196,8 +196,44 @@ class Session } /** - * 删除session数据 + * session设置 下一次请求有效 * @param string $name session名称 + * @param mixed $value session值 + * @param string|null $prefix 作用域(前缀) + * @return void + */ + public static function flash($name, $value) + { + self::set($name, $value); + if (!self::has('__flash__.__time__')) { + self::set('__flash__.__time__', $_SERVER['REQUEST_TIME_FLOAT']); + } + self::push('__flash__', $name); + } + + /** + * 清空当前请求的session数据 + * @return void + */ + public static function flush() + { + if (self::$init) { + $item = self::get('__flash__'); + + if (!empty($item)) { + $time = $item['__time__']; + if ($_SERVER['REQUEST_TIME_FLOAT'] > $time) { + unset($item['__time__']); + self::delete($item); + self::set('__flash__', []); + } + } + } + } + + /** + * 删除session数据 + * @param string|array $name session名称 * @param string|null $prefix 作用域(前缀) * @return void */ @@ -205,7 +241,11 @@ class Session { empty(self::$init) && self::boot(); $prefix = !is_null($prefix) ? $prefix : self::$prefix; - if (strpos($name, '.')) { + if (is_array($name)) { + foreach ($name as $key) { + self::delete($key, $prefix); + } + } elseif (strpos($name, '.')) { list($name1, $name2) = explode('.', $name); if ($prefix) { unset($_SESSION[$prefix][$name1][$name2]); @@ -256,6 +296,22 @@ class Session } } + /** + * 添加数据到一个session数组 + * @param string $key + * @param mixed $value + * @return void + */ + public static function push($key, $value) + { + $array = self::get($key); + if (is_null($array)) { + $array = []; + } + $array[] = $value; + self::set($key, $array); + } + /** * 启动session * @return void diff --git a/core/library/think/Url.php b/core/library/think/Url.php index 2e1fcc19..d8730743 100644 --- a/core/library/think/Url.php +++ b/core/library/think/Url.php @@ -20,6 +20,7 @@ class Url { // 生成URL地址的root protected static $root; + protected static $bindCheck; /** * URL生成 支持路由反射 @@ -31,7 +32,7 @@ class Url */ public static function build($url = '', $vars = '', $suffix = true, $domain = false) { - if (false === $domain && Config::get('url_domain_deploy')) { + if (false === $domain && Route::rules('domain')) { $domain = true; } // 解析URL @@ -40,22 +41,24 @@ class Url $name = substr($url, 1, $pos - 1); $url = 'name' . substr($url, $pos + 1); } - $info = parse_url($url); - $url = !empty($info['path']) ? $info['path'] : ''; - if (isset($info['fragment'])) { - // 解析锚点 - $anchor = $info['fragment']; - if (false !== strpos($anchor, '?')) { - // 解析参数 - list($anchor, $info['query']) = explode('?', $anchor, 2); - } - if (false !== strpos($anchor, '@')) { + if (false === strpos($url, '://') && 0 !== strpos($url, '/')) { + $info = parse_url($url); + $url = !empty($info['path']) ? $info['path'] : ''; + if (isset($info['fragment'])) { + // 解析锚点 + $anchor = $info['fragment']; + if (false !== strpos($anchor, '?')) { + // 解析参数 + list($anchor, $info['query']) = explode('?', $anchor, 2); + } + if (false !== strpos($anchor, '@')) { + // 解析域名 + list($anchor, $domain) = explode('@', $anchor, 2); + } + } elseif (strpos($url, '@') && false === strpos($url, '\\')) { // 解析域名 - list($anchor, $domain) = explode('@', $anchor, 2); + list($url, $domain) = explode('@', $url, 2); } - } elseif (strpos($url, '@')) { - // 解析域名 - list($url, $domain) = explode('@', $url, 2); } // 解析参数 @@ -78,7 +81,7 @@ class Url // 匹配路由命名标识 $url = $match[0]; // 替换可选分隔符 - $url = preg_replace(['/\((\W)\?\)$/', '/\((\W)\?\)/'], ['', '\1'], $url); + $url = preg_replace(['/(\W)\?$/', '/(\W)\?/'], ['', '\1'], $url); if (!empty($match[1])) { $domain = $match[1]; } @@ -110,11 +113,13 @@ class Url } // 检测URL绑定 - $type = Route::getBind('type'); - if ($type) { - $bind = Route::getBind($type); - if (0 === strpos($url, $bind)) { - $url = substr($url, strlen($bind) + 1); + if (!self::$bindCheck) { + $type = Route::getBind('type'); + if ($type) { + $bind = Route::getBind($type); + if (0 === strpos($url, $bind)) { + $url = substr($url, strlen($bind) + 1); + } } } // 还原URL分隔符 @@ -132,9 +137,10 @@ class Url $vars = urldecode(http_build_query($vars)); $url .= $suffix . '?' . $vars . $anchor; } else { + $paramType = Config::get('url_param_type'); foreach ($vars as $var => $val) { if ('' !== trim($val)) { - if (Config::get('url_param_type')) { + if ($paramType) { $url .= $depr . urlencode($val); } else { $url .= $depr . $var . $depr . urlencode($val); @@ -149,12 +155,13 @@ class Url // 检测域名 $domain = self::parseDomain($url, $domain); // URL组装 - $url = $domain . (self::$root ?: Request::instance()->root()) . '/' . ltrim($url, '/'); + $url = $domain . (self::$root ?: Request::instance()->root()) . '/' . ltrim($url, '/'); + self::$bindCheck = false; return $url; } // 直接解析URL地址 - protected static function parseUrl($url, $domain) + protected static function parseUrl($url, &$domain) { $request = Request::instance(); if (0 === strpos($url, '/')) { @@ -170,14 +177,36 @@ class Url // 解析到 模块/控制器/操作 $module = $request->module(); $domains = Route::rules('domain'); - if (isset($domains[$domain]['[bind]'][0])) { - $bindModule = $domains[$domain]['[bind]'][0]; - if ($bindModule && !in_array($bindModule[0], ['\\', '@'])) { - $module = ''; + if (true === $domain && 2 == substr_count($url, '/')) { + $current = $request->host(); + $match = []; + $pos = []; + foreach ($domains as $key => $item) { + if (isset($item['[bind]']) && 0 === strpos($url, $item['[bind]'][0])) { + $pos[$key] = strlen($item['[bind]'][0]) + 1; + $match[] = $key; + $module = ''; + } + } + if ($match) { + $domain = current($match); + foreach ($match as $item) { + if (0 === strpos($current, $item)) { + $domain = $item; + } + } + self::$bindCheck = true; + $url = substr($url, $pos[$domain]); + } + } elseif ($domain) { + if (isset($domains[$domain]['[bind]'][0])) { + $bindModule = $domains[$domain]['[bind]'][0]; + if ($bindModule && !in_array($bindModule[0], ['\\', '@'])) { + $module = ''; + } } - } else { - $module = $module ? $module . '/' : ''; } + $module = $module ? $module . '/' : ''; $controller = Loader::parseName($request->controller()); if ('' == $url) { @@ -200,15 +229,15 @@ class Url if (!$domain) { return ''; } - $request = Request::instance(); + $request = Request::instance(); + $rootDomain = Config::get('url_domain_root'); if (true === $domain) { // 自动判断域名 $domain = $request->host(); - if (Config::get('url_domain_deploy')) { - // 根域名 - $urlDomainRoot = Config::get('url_domain_root'); - $domains = Route::rules('domain'); - $route_domain = array_keys($domains); + + $domains = Route::rules('domain'); + if ($domains) { + $route_domain = array_keys($domains); foreach ($route_domain as $domain_prefix) { if (0 === strpos($domain_prefix, '*.') && strpos($domain, ltrim($domain_prefix, '*.')) !== false) { foreach ($domains as $key => $rule) { @@ -217,13 +246,13 @@ class Url $url = ltrim($url, $rule); $domain = $key; // 生成对应子域名 - if (!empty($urlDomainRoot)) { - $domain .= $urlDomainRoot; + if (!empty($rootDomain)) { + $domain .= $rootDomain; } break; } else if (false !== strpos($key, '*')) { - if (!empty($urlDomainRoot)) { - $domain .= $urlDomainRoot; + if (!empty($rootDomain)) { + $domain .= $rootDomain; } break; } @@ -231,13 +260,15 @@ class Url } } } - } elseif (!strpos($domain, '.')) { - $rootDomain = Config::get('url_domain_root'); + + } else { if (empty($rootDomain)) { $host = $request->host(); $rootDomain = substr_count($host, '.') > 1 ? substr(strstr($host, '.'), 1) : $host; } - $domain .= '.' . $rootDomain; + if (!strpos($domain, $rootDomain)) { + $domain .= '.' . $rootDomain; + } } return ($request->isSsl() ? 'https://' : 'http://') . $domain; } diff --git a/core/library/think/Validate.php b/core/library/think/Validate.php index 3c6e847a..fc38d89a 100644 --- a/core/library/think/Validate.php +++ b/core/library/think/Validate.php @@ -348,16 +348,22 @@ class Validate $result = call_user_func_array($rule, [$value, $data]); } else { // 判断验证类型 - if (is_numeric($key) && strpos($rule, ':')) { - list($type, $rule) = explode(':', $rule, 2); - if (isset($this->alias[$type])) { - // 判断别名 - $type = $this->alias[$type]; + if (is_numeric($key)) { + if (strpos($rule, ':')) { + list($type, $rule) = explode(':', $rule, 2); + if (isset($this->alias[$type])) { + // 判断别名 + $type = $this->alias[$type]; + } + $info = $type; + } elseif (method_exists($this, $rule)) { + $type = $rule; + $info = $rule; + $rule = ''; + } else { + $type = 'is'; + $info = $rule; } - $info = $type; - } elseif (is_numeric($key)) { - $type = 'is'; - $info = $rule; } else { $info = $type = $key; } @@ -377,7 +383,7 @@ class Validate // 验证失败 返回错误信息 if (isset($msg[$i])) { $message = $msg[$i]; - if (is_string($message) && strpos($message, '{%')) { + if (is_string($message) && strpos($message, '{%') === 0) { $message = Lang::get(substr($message, 2, -1)); } } else { @@ -607,6 +613,9 @@ class Validate */ protected function activeUrl($value, $rule) { + if (!in_array($rule, ['A', 'MX', 'NS', 'SOA', 'PTR', 'CNAME', 'AAAA', 'A6', 'SRV', 'NAPTR', 'TXT', 'ANY'])) { + $rule = 'MX'; + } return checkdnsrr($value, $rule); } @@ -715,19 +724,24 @@ class Validate if (!($file instanceof File)) { return false; } - $rule = explode(',', $rule); - list($width, $height, $type) = getimagesize($file->getRealPath()); - if (isset($rule[2])) { - $imageType = strtolower($rule[2]); - if ('jpeg' == $imageType) { - $imageType = 'jpg'; - } - if (image_type_to_extension($type, false) != $imageType) { - return false; + if ($rule) { + $rule = explode(',', $rule); + list($width, $height, $type) = getimagesize($file->getRealPath()); + if (isset($rule[2])) { + $imageType = strtolower($rule[2]); + if ('jpeg' == $imageType) { + $imageType = 'jpg'; + } + if (image_type_to_extension($type, false) != $imageType) { + return false; + } } + + list($w, $h) = $rule; + return $w == $width && $h == $height; + } else { + return in_array($this->getImageType($file->getRealPath()), [1, 2, 3, 6]); } - list($w, $h) = $rule; - return $w == $width && $h == $height; } /** diff --git a/core/library/think/cache/Driver.php b/core/library/think/cache/Driver.php index e0aeb7bc..a2a57795 100644 --- a/core/library/think/cache/Driver.php +++ b/core/library/think/cache/Driver.php @@ -109,6 +109,27 @@ abstract class Driver } } + /** + * 如果不存在则写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param int $expire 有效时间 0为永久 + * @return mixed + */ + public function remember($name, $value, $expire = null) + { + if (!$this->has($name)) { + if ($value instanceof \Closure) { + $value = call_user_func($value); + } + $this->set($name, $value, $expire); + } else { + $value = $this->get($name); + } + return $value; + } + /** * 缓存标签 * @access public diff --git a/core/library/think/db/Builder.php b/core/library/think/db/Builder.php index 69484ffe..c963a704 100644 --- a/core/library/think/db/Builder.php +++ b/core/library/think/db/Builder.php @@ -397,7 +397,15 @@ abstract class Builder protected function parseDateTime($value, $key, $options = [], $bindName = null, $bindType = null) { // 获取时间字段类型 - $type = $this->query->getFieldsType($options); + if (strpos($key, '.')) { + list($table, $key) = explode('.', $key); + if (isset($options['alias']) && $pos = array_search($table, $options['alias'])) { + $table = $pos; + } + } else { + $table = $options['table']; + } + $type = $this->query->getTableInfo($table, 'type'); if (isset($type[$key])) { $info = $type[$key]; } diff --git a/core/library/think/db/Connection.php b/core/library/think/db/Connection.php index f405f9b9..9806b827 100644 --- a/core/library/think/db/Connection.php +++ b/core/library/think/db/Connection.php @@ -421,6 +421,8 @@ abstract class Connection $type = is_array($val) ? $val[1] : PDO::PARAM_STR; if (PDO::PARAM_STR == $type) { $value = $this->quote($value); + } elseif (PDO::PARAM_INT == $type && '' === $value) { + $value = 0; } // 判断占位符 $sql = is_numeric($key) ? @@ -431,7 +433,7 @@ abstract class Connection $sql . ' '); } } - return $sql; + return rtrim($sql); } /** @@ -449,6 +451,9 @@ abstract class Connection // 占位符 $param = is_numeric($key) ? $key + 1 : ':' . $key; if (is_array($val)) { + if (PDO::PARAM_INT == $val[1] && '' === $val[0]) { + $val[0] = 0; + } $result = $this->PDOStatement->bindValue($param, $val[0], $val[1]); } else { $result = $this->PDOStatement->bindValue($param, $val); diff --git a/core/library/think/db/Query.php b/core/library/think/db/Query.php index 5c3e0f0e..5a5597e1 100644 --- a/core/library/think/db/Query.php +++ b/core/library/think/db/Query.php @@ -373,12 +373,13 @@ class Query * @access public * @param string $field 字段名 * @param mixed $default 默认值 + * @param bool $force 强制转为数字类型 * @return mixed */ - public function value($field, $default = null) + public function value($field, $default = null, $force = false) { $result = false; - if (!empty($this->options['cache'])) { + if (empty($options['fetch_sql']) && !empty($this->options['cache'])) { // 判断查询缓存 $cache = $this->options['cache']; if (empty($this->options['table'])) { @@ -397,6 +398,9 @@ class Query return $pdo; } $result = $pdo->fetchColumn(); + if ($force) { + $result = is_numeric($result) ? $result + 0 : $result; + } if (isset($cache)) { // 缓存数据 if (isset($cache['tag'])) { @@ -422,7 +426,7 @@ class Query public function column($field, $key = '') { $result = false; - if (!empty($this->options['cache'])) { + if (empty($options['fetch_sql']) && !empty($this->options['cache'])) { // 判断查询缓存 $cache = $this->options['cache']; if (empty($this->options['table'])) { @@ -489,7 +493,7 @@ class Query */ public function count($field = '*') { - return (int) $this->value('COUNT(' . $field . ') AS tp_count', 0); + return $this->value('COUNT(' . $field . ') AS tp_count', 0, true); } /** @@ -500,29 +504,29 @@ class Query */ public function sum($field = '*') { - return $this->value('SUM(' . $field . ') AS tp_sum', 0) + 0; + return $this->value('SUM(' . $field . ') AS tp_sum', 0, true); } /** * MIN查询 * @access public * @param string $field 字段名 - * @return float|int + * @return mixed */ public function min($field = '*') { - return $this->value('MIN(' . $field . ') AS tp_min', 0) + 0; + return $this->value('MIN(' . $field . ') AS tp_min', 0, true); } /** * MAX查询 * @access public * @param string $field 字段名 - * @return float|int + * @return mixed */ public function max($field = '*') { - return $this->value('MAX(' . $field . ') AS tp_max', 0) + 0; + return $this->value('MAX(' . $field . ') AS tp_max', 0, true); } /** @@ -533,7 +537,7 @@ class Query */ public function avg($field = '*') { - return $this->value('AVG(' . $field . ') AS tp_avg', 0) + 0; + return $this->value('AVG(' . $field . ') AS tp_avg', 0, true); } /** @@ -578,8 +582,6 @@ class Query // 清空查询条件 $this->options = []; return true; - } else { - return $this->setField($field, $step); } } return $this->setField($field, ['exp', $field . '+' . $step]); @@ -609,8 +611,6 @@ class Query // 清空查询条件 $this->options = []; return true; - } else { - return $this->setField($field, $step); } } return $this->setField($field, ['exp', $field . '-' . $step]); @@ -663,28 +663,53 @@ class Query } } } else { - // 传入的表名为数组 - if (is_array($join)) { - if (0 !== $key = key($join)) { - // 设置了键名则键名为表名,键值作为表的别名 - $table = [$key => array_shift($join)]; - $this->alias($table); - } else { - $table = array_shift($join); - } - } else { - $table = trim($join); - if (strpos($table, ' ') && !strpos($table, ')')) { - list($table, $alias) = explode(' ', $table); - $table = [$table => $alias]; - $this->alias($table); - } - } + $table = $this->getJoinTable($join); + $this->options['join'][] = [$table, strtoupper($type), $condition]; } return $this; } + /** + * 获取Join表名及别名 支持 + * ['prefix_table或者子查询'=>'alias'] 'prefix_table alias' 'table alias' + * @access public + * @param array|string $join + * @return array|string + */ + protected function getJoinTable($join, &$alias = null) + { + // 传入的表名为数组 + if (is_array($join)) { + list($table, $alias) = each($join); + } else { + $join = trim($join); + if (false !== strpos($join, '(')) { + // 使用子查询 + $table = $join; + } else { + $prefix = $this->prefix; + if (strpos($join, ' ')) { + // 使用别名 + list($table, $alias) = explode(' ', $join); + } else { + $table = $join; + if (false === strpos($join, '.') && 0 !== strpos($join, '__')) { + $alias = $join; + } + } + if ($prefix && false === strpos($table, '.') && 0 !== strpos($table, $prefix) && 0 !== strpos($table, '__')) { + $table = $this->getTable($table); + } + } + } + if (isset($alias)) { + $table = [$table => $alias]; + $this->alias($table); + } + return $table; + } + /** * 查询SQL组装 union * @access public @@ -767,13 +792,8 @@ class Query } } else { $fields = []; - if (is_array($join)) { - // 支持数据表别名 - list($join, $alias, $table) = array_pad($join, 3, ''); - } else { - $alias = $join; - } - $table = !empty($table) ? $table : $this->getTable($join); + $table = $this->getJoinTable($join, $alias); + if (true === $field) { $fields = $alias . '.*'; } else { @@ -797,9 +817,9 @@ class Query } $this->field($fields); if ($on) { - $this->join($table . ' ' . $alias, $on, $type); + $this->join($table, $on, $type); } else { - $this->table($table . ' ' . $alias); + $this->table($table); } } return $this; @@ -897,13 +917,9 @@ class Query if (is_array($field)) { // 数组批量查询 $where = $field; - } elseif ($field) { + } elseif ($field && is_string($field)) { // 字符串查询 - if (is_numeric($field)) { - $where[] = ['exp', $field]; - } else { - $where[$field] = ['null', '']; - } + $where[$field] = ['null', '']; } } elseif (is_array($op)) { $where[$field] = $param; @@ -924,6 +940,22 @@ class Query } } + /** + * 去除某个查询条件 + * @access public + * @param string $field 查询字段 + * @param string $logic 查询逻辑 and or xor + * @return $this + */ + public function removeWhereField($field, $logic = 'AND') + { + $logic = strtoupper($logic); + if (isset($this->options['where'][$logic][$field])) { + unset($this->options['where'][$logic][$field]); + } + return $this; + } + /** * 指定查询数量 * @access public @@ -993,8 +1025,11 @@ class Query if (!isset($total) && !$simple) { $options = $this->getOptions(); - $total = $this->count(); + if (isset($options['order'])) { + unset($this->options['order']); + } $bind = $this->bind; + $total = $this->count(); $results = $this->options($options)->bind($bind)->page($page, $listRows)->select(); } elseif ($simple) { $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select(); @@ -1014,7 +1049,10 @@ class Query public function table($table) { if (is_string($table)) { - if (strpos($table, ',')) { + if (strpos($table, ')')) { + // 子查询 + $table = $table; + } elseif (strpos($table, ',')) { $tables = explode(',', $table); $table = []; foreach ($tables as $item) { @@ -1174,6 +1212,9 @@ class Query } else { if (isset($this->options['table'])) { $table = is_array($this->options['table']) ? key($this->options['table']) : $this->options['table']; + if (false !== strpos($table, '__')) { + $table = $this->parseSqlTable($table); + } } else { $table = $this->getTable(); } @@ -1595,6 +1636,8 @@ class Query $field = $this->options['with_field']; unset($this->options['with_field']); } + } elseif (isset($info['option']['field'])) { + $field = $info['option']['field']; } $this->field($field, false, $joinTable, $joinAlias, $relation . '__'); $i++; diff --git a/core/library/think/exception/RouteNotFoundException.php b/core/library/think/exception/RouteNotFoundException.php new file mode 100644 index 00000000..6ee2f7b6 --- /dev/null +++ b/core/library/think/exception/RouteNotFoundException.php @@ -0,0 +1,24 @@ + +// +---------------------------------------------------------------------- + +namespace think\exception; + +use think\exception\HttpException; + +class RouteNotFoundException extends HttpException +{ + + public function __construct() + { + parent::__construct(404); + } + +} diff --git a/core/library/think/model/Merge.php b/core/library/think/model/Merge.php index c28d0fd7..de8d9e1a 100644 --- a/core/library/think/model/Merge.php +++ b/core/library/think/model/Merge.php @@ -61,14 +61,14 @@ class Merge extends Model { $class = new static(); $master = $class->name; - $fields = self::getModelField($query, $master, '', $class->mapFields); + $fields = self::getModelField($query, $master, '', $class->mapFields, $class->field); $query->alias($master)->field($fields); foreach ($class->relationModel as $key => $model) { $name = is_int($key) ? $model : $key; $table = is_int($key) ? $query->getTable($name) : $model; $query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk()); - $fields = self::getModelField($query, $name, $table, $class->mapFields); + $fields = self::getModelField($query, $name, $table, $class->mapFields, $class->field); $query->field($fields); } return $query; @@ -81,12 +81,13 @@ class Merge extends Model * @param string $name 模型名称 * @param string $table 关联表名称 * @param array $map 字段映射 + * @param array $fields 查询字段 * @return array */ - protected static function getModelField($query, $name, $table = '', $map = []) + protected static function getModelField($query, $name, $table = '', $map = [], $fields = []) { // 获取模型的字段信息 - $fields = $query->getTableInfo($table, 'fields'); + $fields = $fields ?: $query->getTableInfo($table, 'fields'); $array = []; foreach ($fields as $field) { if ($key = array_search($name . '.' . $field, $map)) { diff --git a/core/library/think/model/Relation.php b/core/library/think/model/Relation.php index 22670bdd..f9675c14 100644 --- a/core/library/think/model/Relation.php +++ b/core/library/think/model/Relation.php @@ -47,7 +47,8 @@ class Relation protected $query; // 关联查询条件 protected $where; - + // 关联查询参数 + protected $option; /** * 架构函数 * @access public @@ -74,6 +75,7 @@ class Relation 'localKey' => $this->localKey, 'alias' => $this->alias, 'joinType' => $this->joinType, + 'option' => $this->option, ]; return $name ? $info[$name] : $info; } @@ -689,8 +691,10 @@ class Relation } $result = call_user_func_array([$this->query, $method], $args); if ($result instanceof \think\db\Query) { + $this->option = $result->getOptions(); return $this; } else { + $this->option = []; return $result; } } else { diff --git a/core/library/think/response/Json.php b/core/library/think/response/Json.php index a137f453..027aa2a3 100644 --- a/core/library/think/response/Json.php +++ b/core/library/think/response/Json.php @@ -27,17 +27,25 @@ class Json extends Response * @access protected * @param mixed $data 要处理的数据 * @return mixed + * @throws \Exception */ protected function output($data) { - // 返回JSON数据格式到客户端 包含状态信息 - $data = json_encode($data, $this->options['json_encode_param']); + try { + // 返回JSON数据格式到客户端 包含状态信息 + $data = json_encode($data, $this->options['json_encode_param']); - if ($data === false) { - throw new \InvalidArgumentException(json_last_error_msg()); + if ($data === false) { + throw new \InvalidArgumentException(json_last_error_msg()); + } + + return $data; + } catch (\Exception $e) { + if ($e->getPrevious()) { + throw $e->getPrevious(); + } + throw $e; } - - return $data; } } diff --git a/core/library/think/response/Jsonp.php b/core/library/think/response/Jsonp.php index fda1183a..b92aa9f6 100644 --- a/core/library/think/response/Jsonp.php +++ b/core/library/think/response/Jsonp.php @@ -30,21 +30,29 @@ class Jsonp extends Response * @access protected * @param mixed $data 要处理的数据 * @return mixed + * @throws \Exception */ protected function output($data) { - // 返回JSON数据格式到客户端 包含状态信息 [当url_common_param为false时是无法获取到$_GET的数据的,故使用Request来获取] - $var_jsonp_handler = Request::instance()->param($this->options['var_jsonp_handler'], ""); - $handler = !empty($var_jsonp_handler) ? $var_jsonp_handler : $this->options['default_jsonp_handler']; + try { + // 返回JSON数据格式到客户端 包含状态信息 [当url_common_param为false时是无法获取到$_GET的数据的,故使用Request来获取] + $var_jsonp_handler = Request::instance()->param($this->options['var_jsonp_handler'], ""); + $handler = !empty($var_jsonp_handler) ? $var_jsonp_handler : $this->options['default_jsonp_handler']; - $data = json_encode($data, $this->options['json_encode_param']); + $data = json_encode($data, $this->options['json_encode_param']); - if ($data === false) { - throw new \InvalidArgumentException(json_last_error_msg()); + if ($data === false) { + throw new \InvalidArgumentException(json_last_error_msg()); + } + + $data = $handler . '(' . $data . ');'; + return $data; + } catch (\Exception $e) { + if ($e->getPrevious()) { + throw $e->getPrevious(); + } + throw $e; } - - $data = $handler . '(' . $data . ');'; - return $data; } } diff --git a/core/library/think/response/Redirect.php b/core/library/think/response/Redirect.php index 82a5fe32..0d65e5e3 100644 --- a/core/library/think/response/Redirect.php +++ b/core/library/think/response/Redirect.php @@ -53,10 +53,10 @@ class Redirect extends Response { if (is_array($name)) { foreach ($name as $key => $val) { - Session::set($key, $val); + Session::flash($key, $val); } } else { - Session::set($name, $value); + Session::flash($name, $value); } return $this; } diff --git a/core/library/think/view/driver/Think.php b/core/library/think/view/driver/Think.php index 33729b44..db1d9816 100644 --- a/core/library/think/view/driver/Think.php +++ b/core/library/think/view/driver/Think.php @@ -24,6 +24,8 @@ class Think private $template; // 模板引擎参数 protected $config = [ + // 视图基础目录(集中式) + 'view_base' => '', // 模板起始路径 'view_path' => '', // 模板文件后缀 @@ -103,18 +105,21 @@ class Think */ private function parseTemplate($template) { + // 分析模板文件规则 + $request = Request::instance(); // 获取视图根目录 if (strpos($template, '@')) { // 跨模块调用 list($module, $template) = explode('@', $template); - $path = APP_PATH . $module . DS . 'view' . DS; + } + if ($this->config['view_base']) { + // 基础视图目录 + $module = isset($module) ? $module : $request->module(); + $path = $this->config['view_base'] . ($module ? $module . DS : ''); } else { - // 当前视图目录 - $path = $this->config['view_path']; + $path = isset($module) ? APP_PATH . $module . DS . 'view' . DS : $this->config['view_path']; } - // 分析模板文件规则 - $request = Request::instance(); $controller = Loader::parseName($request->controller()); if ($controller && 0 !== strpos($template, '/')) { $depr = $this->config['view_depr']; diff --git a/core/library/traits/model/SoftDelete.php b/core/library/traits/model/SoftDelete.php index 4bb072dc..9d855c76 100644 --- a/core/library/traits/model/SoftDelete.php +++ b/core/library/traits/model/SoftDelete.php @@ -27,7 +27,8 @@ trait SoftDelete public static function withTrashed() { $model = new static(); - return $model->db(); + $field = $model->getDeleteTimeField(true); + return $model->db(false)->removeWhereField($field); } /** @@ -38,8 +39,8 @@ trait SoftDelete public static function onlyTrashed() { $model = new static(); - $field = $model->getDeleteTimeField(); - return $model->db()->where($field, 'exp', 'is not null'); + $field = $model->getDeleteTimeField(true); + return $model->db(false)->where($field, 'exp', 'is not null'); } /** @@ -138,7 +139,8 @@ trait SoftDelete $field = $this->db(false)->getTable() . '.' . $field; } if (!$read && strpos($field, '.')) { - list($alias, $field) = explode('.', $field); + $array = explode('.', $field); + $field = array_pop($array); } return $field; }