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