Merge pull request #1 from top-think/master

update thinkphp
This commit is contained in:
HyperQing
2016-10-28 20:13:24 -05:00
committed by GitHub
16 changed files with 280 additions and 147 deletions

View File

@@ -9,7 +9,7 @@
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
define('THINK_VERSION', '5.0.2dev');
define('THINK_VERSION', '5.0.3beta');
define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php');

View File

@@ -85,6 +85,8 @@ return [
'url_route_on' => true,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 路由使用完整匹配
'route_complete_match' => false,
// 是否强制使用路由
'url_route_must' => false,
// 域名部署

View File

@@ -298,7 +298,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 +359,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)) {

View File

@@ -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;
@@ -369,34 +370,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);
}
/**
@@ -552,7 +548,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) {

View File

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

View File

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

View File

@@ -1241,8 +1241,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'])) {

View File

@@ -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 = [];
/**
* 注册变量规则
@@ -150,6 +153,7 @@ class Route
} elseif (!is_null($value)) {
self::$rules['name'][$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,13 +304,13 @@ 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;
self::name($name, [$key, $vars, self::$domain]);
$key = $group ? $group . ($rule ? '/' . $rule : '') : $rule;
self::name(strtolower($name), [$key, $vars, self::$domain]);
}
if ($group) {
if ('*' != $type) {
@@ -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];
// 检测域名部署
@@ -831,6 +858,7 @@ class Route
$rule = self::getRouteExpress($item);
}
if (!empty($rule['route']) && self::checkOption($rule['option'], $request)) {
self::setOption($rule['option']);
return self::parseRule($item, $rule['route'], $url, $rule['option']);
}
}
@@ -894,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;
@@ -909,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']);
}
@@ -1091,7 +1121,9 @@ class Route
{
// 请求类型检测
if ((isset($option['method']) && is_string($option['method']) && false === stripos($option['method'], $request->method()))
|| (isset($option['ext']) && false === stripos($option['ext'], $request->ext())) // 伪静态后缀检测
|| (!empty($option['ajax']) && !$request->isAjax()) // Ajax检测
|| (!empty($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检测
@@ -1162,8 +1194,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);
@@ -1176,15 +1209,22 @@ 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;
if (is_file($dir . DS . str_replace('.', DS, $val) . $suffix . EXT)) {
$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;
@@ -1195,8 +1235,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];

View File

@@ -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
@@ -112,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分隔符
@@ -152,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, '/')) {
@@ -173,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) {
@@ -203,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) {
@@ -220,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;
}
@@ -234,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;
}

View File

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

View File

@@ -433,7 +433,7 @@ abstract class Connection
$sql . ' ');
}
}
return $sql;
return rtrim($sql);
}
/**

View File

@@ -669,11 +669,18 @@ class Query
$table = array_shift($join);
}
} else {
$table = trim($join);
if (strpos($table, ' ') && !strpos($table, ')')) {
list($table, $alias) = explode(' ', $table);
$prefix = $this->prefix;
$join = trim($join);
if ($prefix && false === strpos($join, ' ') && false === strpos($join, '(') && false === strpos($join, '.') && 0 !== strpos($join, $prefix) && 0 !== strpos($join, '__')) {
$table = $this->getTable($join);
$table = [$table => $join];
$this->alias($table);
} elseif (strpos($join, ' ') && !strpos($join, ')')) {
list($table, $alias) = explode(' ', $join);
$table = [$table => $alias];
$this->alias($table);
} else {
$table = $join;
}
}
$this->options['join'][] = [$table, strtoupper($type), $condition];
@@ -763,13 +770,19 @@ class Query
}
} else {
$fields = [];
$prefix = $this->prefix;
if (is_array($join)) {
// 支持数据表别名
list($join, $alias, $table) = array_pad($join, 3, '');
list($table, $alias) = each($join);
} elseif ($prefix && false === strpos($join, ' ') && 0 !== strpos($join, $prefix) && 0 !== strpos($join, '__')) {
$table = $this->getTable($join);
$alias = $join;
} elseif (strpos($join, ' ')) {
list($table, $alias) = explode(' ', $join);
} else {
$alias = $join;
}
$table = !empty($table) ? $table : $this->getTable($join);
$table = isset($table) ? [$table => $alias] : $alias;
if (true === $field) {
$fields = $alias . '.*';
} else {
@@ -793,9 +806,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;
@@ -893,13 +906,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;
@@ -989,8 +998,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();

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

View File

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

View File

@@ -27,7 +27,7 @@ trait SoftDelete
public static function withTrashed()
{
$model = new static();
return $model->db();
return $model->db(false);
}
/**
@@ -39,7 +39,7 @@ trait SoftDelete
{
$model = new static();
$field = $model->getDeleteTimeField();
return $model->db()->where($field, 'exp', 'is not null');
return $model->db(false)->where($field, 'exp', 'is not null');
}
/**

View File

@@ -25,13 +25,13 @@ class urlTest extends \PHPUnit_Framework_TestCase
public function setUp()
{
Route::rules(['GET' => [],
'POST' => [],
'PUT' => [],
'DELETE' => [],
'PATCH' => [],
'HEAD' => [],
'OPTIONS' => [],
Route::rules(['get' => [],
'post' => [],
'put' => [],
'delete' => [],
'patch' => [],
'head' => [],
'options' => [],
'*' => [],
'alias' => [],
'domain' => [],