更新内核
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -130,6 +130,9 @@ class Response
|
||||
|
||||
// 监听response_end
|
||||
Hook::listen('response_end', $this);
|
||||
|
||||
// 清空当次请求有效的数据
|
||||
Session::flush();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
21
core/library/think/cache/Driver.php
vendored
21
core/library/think/cache/Driver.php
vendored
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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++;
|
||||
|
||||
24
core/library/think/exception/RouteNotFoundException.php
Normal file
24
core/library/think/exception/RouteNotFoundException.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
namespace think\exception;
|
||||
|
||||
use think\exception\HttpException;
|
||||
|
||||
class RouteNotFoundException extends HttpException
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(404);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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来获取<xiaobo.sun@qq.com>]
|
||||
$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来获取<xiaobo.sun@qq.com>]
|
||||
$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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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'];
|
||||
|
||||
Reference in New Issue
Block a user