内核更新

This commit is contained in:
2016-08-23 18:01:41 +08:00
parent 707ebdf51d
commit 94582d442c
22 changed files with 249 additions and 286 deletions

View File

@@ -15,6 +15,8 @@ return [
'app_status' => '', 'app_status' => '',
// 是否支持多模块 // 是否支持多模块
'app_multi_module' => true, 'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间 // 注册的根命名空间
'root_namespace' => [], 'root_namespace' => [],
// 扩展配置文件 // 扩展配置文件

View File

@@ -79,6 +79,17 @@ class App
is_null($request) && $request = Request::instance(); is_null($request) && $request = Request::instance();
$config = self::initCommon(); $config = self::initCommon();
if (defined('BIND_MODULE')) {
// 模块/控制器绑定
BIND_MODULE && Route::bind(BIND_MODULE);
} elseif ($config['auto_bind_module']) {
// 入口自动绑定
$name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
Route::bind($name);
}
}
$request->filter($config['default_filter']); $request->filter($config['default_filter']);
try { try {
@@ -102,8 +113,13 @@ class App
// 记录当前调度信息 // 记录当前调度信息
$request->dispatch($dispatch); $request->dispatch($dispatch);
// 记录路由信息 // 记录路由和请求信息
self::$debug && Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info'); if (self::$debug) {
Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
}
// 监听app_begin // 监听app_begin
Hook::listen('app_begin', $dispatch); Hook::listen('app_begin', $dispatch);
@@ -156,11 +172,6 @@ class App
// 监听app_end // 监听app_end
Hook::listen('app_end', $response); Hook::listen('app_end', $response);
// Trace调试注入
if (Config::get('app_trace')) {
Debug::inject($response);
}
return $response; return $response;
} }
@@ -322,7 +333,7 @@ class App
try { try {
$instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']); $instance = Loader::controller($controller, $config['url_controller_layer'], $config['controller_suffix'], $config['empty_controller']);
if (is_null($instance)) { if (is_null($instance)) {
throw new HttpException(404, 'controller not exists:' . $controller); throw new HttpException(404, 'controller not exists:' . Loader::parseName($controller, 1));
} }
// 获取当前操作名 // 获取当前操作名
$action = $actionName . $config['action_suffix']; $action = $actionName . $config['action_suffix'];
@@ -374,7 +385,7 @@ class App
} }
} }
// 应用命名空间 // 注册应用命名空间
self::$namespace = $config['app_namespace']; self::$namespace = $config['app_namespace'];
Loader::addNamespace($config['app_namespace'], APP_PATH); Loader::addNamespace($config['app_namespace'], APP_PATH);
if (!empty($config['root_namespace'])) { if (!empty($config['root_namespace'])) {

View File

@@ -159,9 +159,10 @@ class Debug
* @param mixed $var 变量 * @param mixed $var 变量
* @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串 * @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
* @param string $label 标签 默认为空 * @param string $label 标签 默认为空
* @param integer $flags htmlspecialchars flags
* @return void|string * @return void|string
*/ */
public static function dump($var, $echo = true, $label = null) public static function dump($var, $echo = true, $label = null, $flags = ENT_SUBSTITUTE)
{ {
$label = (null === $label) ? '' : rtrim($label) . ':'; $label = (null === $label) ? '' : rtrim($label) . ':';
ob_start(); ob_start();
@@ -172,7 +173,7 @@ class Debug
$output = PHP_EOL . $label . $output . PHP_EOL; $output = PHP_EOL . $label . $output . PHP_EOL;
} else { } else {
if (!extension_loaded('xdebug')) { if (!extension_loaded('xdebug')) {
$output = htmlspecialchars($output, ENT_QUOTES); $output = htmlspecialchars($output, $flags);
} }
$output = '<pre>' . $label . $output . '</pre>'; $output = '<pre>' . $label . $output . '</pre>';
} }
@@ -184,14 +185,12 @@ class Debug
} }
} }
public static function inject(Response $response) public static function inject(Response $response, &$content)
{ {
$config = Config::get('trace'); $config = Config::get('trace');
$type = isset($config['type']) ? $config['type'] : 'Html'; $type = isset($config['type']) ? $config['type'] : 'Html';
$request = Request::instance(); $request = Request::instance();
$accept = $request->header('accept'); $class = false !== strpos($type, '\\') ? $type : '\\think\\debug\\' . ucwords($type);
$contentType = $response->getHeader('Content-Type');
$class = false !== strpos($type, '\\') ? $type : '\\think\\debug\\' . ucwords($type);
unset($config['type']); unset($config['type']);
if (class_exists($class)) { if (class_exists($class)) {
$trace = new $class($config); $trace = new $class($config);
@@ -205,14 +204,12 @@ class Debug
$output = $trace->output($response, Log::getLog()); $output = $trace->output($response, Log::getLog());
if (is_string($output)) { if (is_string($output)) {
// trace调试信息注入 // trace调试信息注入
$content = $response->getContent(); $pos = strripos($content, '</body>');
$pos = strripos($content, '</body>');
if (false !== $pos) { if (false !== $pos) {
$content = substr($content, 0, $pos) . $output . substr($content, $pos); $content = substr($content, 0, $pos) . $output . substr($content, $pos);
} else { } else {
$content = $content . $output; $content = $content . $output;
} }
$response->content($content);
} }
} }
} }

View File

@@ -607,7 +607,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @param array $data 数据 * @param array $data 数据
* @param array $where 更新条件 * @param array $where 更新条件
* @param string $sequence 自增序列名 * @param string $sequence 自增序列名
* @return integer * @return integer|false
*/ */
public function save($data = [], $where = [], $sequence = null) public function save($data = [], $where = [], $sequence = null)
{ {
@@ -729,16 +729,35 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* 保存多个数据到当前数据对象 * 保存多个数据到当前数据对象
* @access public * @access public
* @param array $dataSet 数据 * @param array $dataSet 数据
* @param boolean $replace 是否自动识别更新和写入
* @return array|false * @return array|false
*/ */
public function saveAll($dataSet) public function saveAll($dataSet, $replace = true)
{ {
if ($this->validate) {
// 数据批量验证
$validate = $this->validate;
foreach ($dataSet as $data) {
if (!$this->validate($validate)->validateData($data)) {
return false;
}
}
}
$result = []; $result = [];
$db = $this->db(); $db = $this->db();
$db->startTrans(); $db->startTrans();
try { try {
$pk = $this->getPk();
if (is_string($pk) && $replace) {
$auto = true;
}
foreach ($dataSet as $key => $data) { foreach ($dataSet as $key => $data) {
$result[$key] = self::create($data); if (!empty($auto) && isset($data[$pk])) {
$result[$key] = self::update($data);
} else {
$result[$key] = self::create($data);
}
} }
$db->commit(); $db->commit();
return $result; return $result;
@@ -969,8 +988,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
public static function update($data = [], $where = []) public static function update($data = [], $where = [])
{ {
$model = new static(); $model = new static();
$model->isUpdate(true)->save($data, $where); $result = $model->isUpdate(true)->save($data, $where);
return $model; return $model;
} }

View File

@@ -617,7 +617,7 @@ class Request
$vars = []; $vars = [];
} }
// 当前请求参数和URL地址中的参数合并 // 当前请求参数和URL地址中的参数合并
$this->param = array_merge($this->route(false), $this->get(false), $vars); $this->param = array_merge($this->get(false), $vars, $this->route(false));
} }
if (true === $name) { if (true === $name) {
// 获取包含文件上传信息的数组 // 获取包含文件上传信息的数组
@@ -753,7 +753,7 @@ class Request
$this->param = []; $this->param = [];
return $this->request = array_merge($this->request, $name); return $this->request = array_merge($this->request, $name);
} }
return $this->input($this->request ?: $_REQUEST, $name, $default, $filter); return $this->input($this->request, $name, $default, $filter);
} }
/** /**

View File

@@ -11,6 +11,8 @@
namespace think; namespace think;
use think\Config;
use think\Debug;
use think\response\Json as JsonResponse; use think\response\Json as JsonResponse;
use think\response\Jsonp as JsonpResponse; use think\response\Jsonp as JsonpResponse;
use think\response\Redirect as RedirectResponse; use think\response\Redirect as RedirectResponse;
@@ -93,6 +95,11 @@ class Response
// 处理输出数据 // 处理输出数据
$data = $this->getContent(); $data = $this->getContent();
// Trace调试注入
if (Config::get('app_trace')) {
Debug::inject($this, $data);
}
if (!headers_sent() && !empty($this->header)) { if (!headers_sent() && !empty($this->header)) {
// 发送状态码 // 发送状态码
http_response_code($this->code); http_response_code($this->code);
@@ -170,14 +177,14 @@ class Response
public function content($content) public function content($content)
{ {
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([ if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
$content, $content,
'__toString', '__toString',
]) ])
) { ) {
throw new \InvalidArgumentException(sprintf('variable type error %s', gettype($content))); throw new \InvalidArgumentException(sprintf('variable type error %s', gettype($content)));
} }
$this->content = (string)$content; $this->content = (string) $content;
return $this; return $this;
} }
@@ -274,18 +281,18 @@ class Response
*/ */
public function getContent() public function getContent()
{ {
if ($this->content == null) { if (null == $this->content) {
$content = $this->output($this->data); $content = $this->output($this->data);
if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([ if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([
$content, $content,
'__toString', '__toString',
]) ])
) { ) {
throw new \InvalidArgumentException(sprintf('variable type error %s', gettype($content))); throw new \InvalidArgumentException(sprintf('variable type error %s', gettype($content)));
} }
$this->content = (string)$content; $this->content = (string) $content;
} }
return $this->content; return $this->content;
} }

View File

@@ -101,22 +101,20 @@ class Route
foreach ($domain as $key => $item) { foreach ($domain as $key => $item) {
self::domain($key, $item, $option, $pattern); self::domain($key, $item, $option, $pattern);
} }
} elseif ($rule instanceof \Closure) {
// 执行闭包
self::setDomain($domain);
call_user_func_array($rule, []);
self::setDomain(null);
} elseif (is_array($rule)) {
self::setDomain($domain);
self::group('', function () use ($rule) {
// 动态注册域名的路由规则
self::registerRules($rule);
}, $option, $pattern);
self::setDomain(null);
} else { } else {
if ($rule instanceof \Closure) { self::$rules['domain'][$domain]['[bind]'] = [$rule, $option, $pattern];
// 执行闭包
self::setDomain($domain);
call_user_func_array($rule, []);
self::setDomain(null);
} elseif (is_array($rule)) {
self::setDomain($domain);
self::group('', function () use ($rule) {
// 动态注册域名的路由规则
self::registerRules($rule);
}, $option, $pattern);
self::setDomain(null);
} else {
self::$rules['domain'][$domain]['[bind]'] = [$rule, $option, $pattern];
}
} }
} }
@@ -284,11 +282,20 @@ class Route
} elseif (is_string($route)) { } elseif (is_string($route)) {
$name = $route; $name = $route;
} }
if ('$' == substr($rule, -1, 1)) { if (!isset($option['complete_match'])) {
if (Config::get('route_complete_match')) {
$option['complete_match'] = true;
} elseif ('$' == substr($rule, -1, 1)) {
// 是否完整匹配
$option['complete_match'] = true;
$rule = substr($rule, 0, -1);
}
} elseif (empty($option['complete_match']) && '$' == substr($rule, -1, 1)) {
// 是否完整匹配 // 是否完整匹配
$option['complete_match'] = true; $option['complete_match'] = true;
$rule = substr($rule, 0, -1); $rule = substr($rule, 0, -1);
} }
if ('/' != $rule) { if ('/' != $rule) {
$rule = trim($rule, '/'); $rule = trim($rule, '/');
} }
@@ -864,14 +871,20 @@ class Route
continue; continue;
} }
if (isset($option['ext'])) {
// 路由ext参数 优先于系统配置的URL伪静态后缀参数
$url = preg_replace('/\.' . $request->ext() . '$/i', '', $url);
}
if (is_array($rule)) { if (is_array($rule)) {
// 分组路由 // 分组路由
if (($pos = strpos($key, ':')) || ($pos = strpos($key, '<'))) { $pos = strpos(str_replace('<', ':', $key), ':');
if (false !== $pos) {
$str = substr($key, 0, $pos); $str = substr($key, 0, $pos);
} else { } else {
$str = $key; $str = $key;
} }
if (is_string($str) && 0 !== strpos($url, $str)) { if (is_string($str) && $str && 0 !== strpos($url, $str)) {
continue; continue;
} }
@@ -1270,26 +1283,6 @@ class Route
*/ */
private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = [], $merge = false) private static function parseRule($rule, $route, $pathinfo, $option = [], $matches = [], $merge = false)
{ {
// 检测是否定义路由
if (!empty($option['after_behavior'])) {
if ($option['after_behavior'] instanceof \Closure) {
$result = call_user_func_array($option['after_behavior'], [$route]);
} else {
foreach ((array) $option['after_behavior'] as $behavior) {
$result = Hook::exec($behavior, '', $route);
if (!is_null($result)) {
break;
}
}
}
// 路由规则重定向
if ($result instanceof Response) {
return ['type' => 'response', 'response' => $result, 'params' => $matches];
} elseif (is_array($result)) {
return $result;
}
}
// 解析路由规则 // 解析路由规则
if ($rule) { if ($rule) {
$rule = explode('/', $rule); $rule = explode('/', $rule);
@@ -1311,6 +1304,7 @@ class Route
} else { } else {
$paths = explode('/', $pathinfo); $paths = explode('/', $pathinfo);
} }
// 获取路由地址规则 // 获取路由地址规则
if (is_string($route) && isset($option['prefix'])) { if (is_string($route) && isset($option['prefix'])) {
// 路由地址前缀 // 路由地址前缀
@@ -1325,6 +1319,32 @@ class Route
} }
} }
} }
// 解析额外参数
self::parseUrlParams(empty($paths) ? '' : implode('/', $paths), $matches);
// 记录匹配的路由信息
Request::instance()->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option, 'var' => $matches]);
// 检测路由after行为
if (!empty($option['after_behavior'])) {
if ($option['after_behavior'] instanceof \Closure) {
$result = call_user_func_array($option['after_behavior'], []);
} else {
foreach ((array) $option['after_behavior'] as $behavior) {
$result = Hook::exec($behavior, '');
if (!is_null($result)) {
break;
}
}
}
// 路由规则重定向
if ($result instanceof Response) {
return ['type' => 'response', 'response' => $result, 'params' => $matches];
} elseif (is_array($result)) {
return $result;
}
}
if ($route instanceof \Closure) { if ($route instanceof \Closure) {
// 执行闭包 // 执行闭包
$result = ['type' => 'function', 'function' => $route, 'params' => $matches]; $result = ['type' => 'function', 'function' => $route, 'params' => $matches];
@@ -1342,10 +1362,6 @@ class Route
// 路由到模块/控制器/操作 // 路由到模块/控制器/操作
$result = self::parseModule($route); $result = self::parseModule($route);
} }
// 解析额外参数
self::parseUrlParams(empty($paths) ? '' : implode('/', $paths), $matches);
// 记录匹配的路由信息
Request::instance()->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option]);
return $result; return $result;
} }
@@ -1367,7 +1383,8 @@ class Route
// 操作方法前缀支持 // 操作方法前缀支持
$action = 0 !== strpos($action, self::$methodPrefix[$method]) ? self::$methodPrefix[$method] . $action : $action; $action = 0 !== strpos($action, self::$methodPrefix[$method]) ? self::$methodPrefix[$method] . $action : $action;
} }
$_GET = array_merge($_GET, $var); // 设置当前请求的路由变量
Request::instance()->route($var);
// 路由到模块/控制器/操作 // 路由到模块/控制器/操作
return ['type' => 'module', 'module' => [$module, $controller, $action], 'convert' => false]; return ['type' => 'module', 'module' => [$module, $controller, $action], 'convert' => false];
} }
@@ -1379,7 +1396,7 @@ class Route
* @param array $var 变量 * @param array $var 变量
* @return void * @return void
*/ */
private static function parseUrlParams($url, $var = []) private static function parseUrlParams($url, &$var = [])
{ {
if ($url) { if ($url) {
if (Config::get('url_param_type')) { if (Config::get('url_param_type')) {

View File

@@ -17,6 +17,7 @@ use think\exception\ClassNotFoundException;
class Session class Session
{ {
protected static $prefix = ''; protected static $prefix = '';
protected static $init = null;
/** /**
* 设置或者获取session作用域前缀 * 设置或者获取session作用域前缀
@@ -98,6 +99,23 @@ class Session
} }
if ($isDoStart) { if ($isDoStart) {
session_start(); session_start();
self::$init = true;
} else {
self::$init = false;
}
}
/**
* session自动启动或者初始化
* @return void
*/
public static function boot()
{
if (is_null(self::$init)) {
self::init();
} elseif (false === self::$init) {
session_start();
self::$init = true;
} }
} }
@@ -110,7 +128,8 @@ class Session
*/ */
public static function set($name, $value = '', $prefix = null) public static function set($name, $value = '', $prefix = null)
{ {
!isset($_SESSION) && self::init(); empty(self::$init) && self::boot();
$prefix = !is_null($prefix) ? $prefix : self::$prefix; $prefix = !is_null($prefix) ? $prefix : self::$prefix;
if (strpos($name, '.')) { if (strpos($name, '.')) {
// 二维数组赋值 // 二维数组赋值
@@ -135,7 +154,7 @@ class Session
*/ */
public static function get($name = '', $prefix = null) public static function get($name = '', $prefix = null)
{ {
!isset($_SESSION) && self::init(); empty(self::$init) && self::boot();
$prefix = !is_null($prefix) ? $prefix : self::$prefix; $prefix = !is_null($prefix) ? $prefix : self::$prefix;
if ('' == $name) { if ('' == $name) {
// 获取全部的session // 获取全部的session
@@ -167,7 +186,7 @@ class Session
*/ */
public static function delete($name, $prefix = null) public static function delete($name, $prefix = null)
{ {
!isset($_SESSION) && self::init(); empty(self::$init) && self::boot();
$prefix = !is_null($prefix) ? $prefix : self::$prefix; $prefix = !is_null($prefix) ? $prefix : self::$prefix;
if (strpos($name, '.')) { if (strpos($name, '.')) {
list($name1, $name2) = explode('.', $name); list($name1, $name2) = explode('.', $name);
@@ -192,7 +211,7 @@ class Session
*/ */
public static function clear($prefix = null) public static function clear($prefix = null)
{ {
!isset($_SESSION) && self::init(); empty(self::$init) && self::boot();
$prefix = !is_null($prefix) ? $prefix : self::$prefix; $prefix = !is_null($prefix) ? $prefix : self::$prefix;
if ($prefix) { if ($prefix) {
unset($_SESSION[$prefix]); unset($_SESSION[$prefix]);
@@ -209,7 +228,7 @@ class Session
*/ */
public static function has($name, $prefix = null) public static function has($name, $prefix = null)
{ {
!isset($_SESSION) && self::init(); empty(self::$init) && self::boot();
$prefix = !is_null($prefix) ? $prefix : self::$prefix; $prefix = !is_null($prefix) ? $prefix : self::$prefix;
if (strpos($name, '.')) { if (strpos($name, '.')) {
// 支持数组 // 支持数组
@@ -227,6 +246,7 @@ class Session
public static function start() public static function start()
{ {
session_start(); session_start();
self::$init = true;
} }
/** /**
@@ -240,6 +260,7 @@ class Session
} }
session_unset(); session_unset();
session_destroy(); session_destroy();
self::$init = null;
} }
/** /**
@@ -260,5 +281,6 @@ class Session
{ {
// 暂停session // 暂停session
session_write_close(); session_write_close();
self::$init = false;
} }
} }

View File

@@ -11,8 +11,6 @@
namespace think; namespace think;
use think\App;
use think\Cache;
use think\Config; use think\Config;
use think\Request; use think\Request;
use think\Route; use think\Route;
@@ -68,13 +66,15 @@ class Url
parse_str($vars, $vars); parse_str($vars, $vars);
} }
if (isset($info['query'])) {
// 解析地址里面参数 合并到vars
parse_str($info['query'], $params);
$vars = array_merge($params, $vars);
}
if ($url) { if ($url) {
$rule = Route::name(isset($name) ? $name : $url); $rule = Route::name(isset($name) ? $name : $url . (isset($info['query']) ? '?' . $info['query'] : ''));
if (is_null($rule) && isset($info['query'])) {
$rule = Route::name($url);
// 解析地址里面参数 合并到vars
parse_str($info['query'], $params);
$vars = array_merge($params, $vars);
unset($info['query']);
}
} }
if (!empty($rule) && $match = self::getRuleUrl($rule, $vars)) { if (!empty($rule) && $match = self::getRuleUrl($rule, $vars)) {
// 匹配路由命名标识 快速生成 // 匹配路由命名标识 快速生成
@@ -85,16 +85,13 @@ class Url
} elseif (!empty($rule) && isset($name)) { } elseif (!empty($rule) && isset($name)) {
throw new \InvalidArgumentException('route name not exists:' . $name); throw new \InvalidArgumentException('route name not exists:' . $name);
} else { } else {
// 获取路由别名 if (isset($info['query'])) {
$alias = self::getRouteAlias(); // 解析地址里面参数 合并到vars
// 检测路由 parse_str($info['query'], $params);
if (0 !== strpos($url, '/') && isset($alias[$url]) && $match = self::getRouteUrl($alias[$url], $vars)) { $vars = array_merge($params, $vars);
// 处理路由规则中的特殊字符
$url = $match;
} else {
// 路由不存在 直接解析
$url = self::parseUrl($url, $domain);
} }
// 路由不存在 直接解析
$url = self::parseUrl($url, $domain);
} }
// 检测URL绑定 // 检测URL绑定
@@ -222,18 +219,6 @@ class Url
return $domain; return $domain;
} }
// 检测路由规则中的变量是否有传入
protected static function pattern($pattern, $vars)
{
foreach ($pattern as $key => $type) {
if (1 == $type && !isset($vars[$key])) {
// 变量未设置
return false;
}
}
return true;
}
// 解析URL后缀 // 解析URL后缀
protected static function parseSuffix($suffix) protected static function parseSuffix($suffix)
{ {
@@ -246,39 +231,6 @@ class Url
return (empty($suffix) || 0 === strpos($suffix, '.')) ? $suffix : '.' . $suffix; return (empty($suffix) || 0 === strpos($suffix, '.')) ? $suffix : '.' . $suffix;
} }
// 匹配路由地址
public static function getRouteUrl($alias, &$vars = [])
{
foreach ($alias as $key => $val) {
list($url, $pattern, $param) = $val;
// 检查变量匹配
$array = $vars;
$match = false;
if ($pattern && self::pattern($pattern, $vars)) {
foreach ($pattern as $key => $val) {
if (isset($vars[$key])) {
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key . '', '<' . $key . '>'], $vars[$key], $url);
unset($array[$key]);
} else {
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>'], '', $url);
}
}
$match = true;
} elseif (empty($pattern) && array_intersect_assoc($param, $array) == $param) {
$match = true;
}
if ($match && !empty($param) && array_intersect_assoc($param, $array) != $param) {
$match = false;
}
if ($match) {
// 存在变量定义
$vars = array_diff_key($array, $param);
return $url;
}
}
return false;
}
// 匹配路由地址 // 匹配路由地址
public static function getRuleUrl($rule, &$vars = []) public static function getRuleUrl($rule, &$vars = [])
{ {
@@ -288,7 +240,7 @@ class Url
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key . '', '<' . $key . '>'], $vars[$key], $url); $url = str_replace(['[:' . $key . ']', '<' . $key . '?>', ':' . $key . '', '<' . $key . '>'], $vars[$key], $url);
unset($vars[$key]); unset($vars[$key]);
} elseif (2 == $val) { } elseif (2 == $val) {
$url = str_replace(['[:' . $key . ']', '<' . $key . '?>'], '', $url); $url = str_replace(['/[:' . $key . ']', '[:' . $key . ']', '<' . $key . '?>'], '', $url);
} else { } else {
return false; return false;
} }
@@ -296,69 +248,6 @@ class Url
return $url; return $url;
} }
// 生成路由映射并缓存
private static function getRouteAlias()
{
if ($item = Cache::get('think_route_map')) {
return $item;
}
// 获取路由定义
$array = Route::rules();
foreach ($array as $type => $rules) {
foreach ($rules as $rule => $val) {
if (true === $val || empty($val['rule'])) {
continue;
}
$route = $val['route'];
$vars = $val['var'];
if (is_array($val['rule'])) {
foreach ($val['rule'] as $val) {
$key = $val['rule'];
$route = $val['route'];
$var = $val['var'];
$param = [];
if (is_array($route)) {
$route = implode('\\', $route);
} elseif ($route instanceof \Closure) {
continue;
} elseif (strpos($route, '?')) {
list($route, $str) = explode('?', $route, 2);
parse_str($str, $param);
}
$var = array_merge($vars, $var);
$item[$route][] = [$rule . '/' . $key, $var, $param];
}
} else {
$param = [];
if (is_array($route)) {
$route = implode('\\', $route);
} elseif ($route instanceof \Closure) {
continue;
} elseif (strpos($route, '?')) {
list($route, $str) = explode('?', $route, 2);
parse_str($str, $param);
}
$item[$route][] = [$rule, $vars, $param];
}
}
}
// 检测路由别名
$alias = Route::rules('alias');
foreach ($alias as $rule => $route) {
$route = is_array($route) ? $route[0] : $route;
$item[$route][] = [$rule, [], []];
}
!App::$debug && Cache::set('think_route_map', $item);
return $item;
}
// 清空路由别名缓存
public static function clearAliasCache()
{
Cache::rm('think_route_map');
}
// 指定当前生成URL地址的root // 指定当前生成URL地址的root
public static function root($root) public static function root($root)
{ {

View File

@@ -351,7 +351,7 @@ abstract class Connection
$result = $this->PDOStatement->execute(); $result = $this->PDOStatement->execute();
// 调试结束 // 调试结束
$this->debug(false); $this->debug(false);
$procedure = 0 === strpos(strtolower(substr(trim($sql), 0, 4)), 'call'); $procedure = in_array(strtolower(substr(trim($sql), 0, 4)), ['call', 'exec']);
return $this->getResult($class, $procedure); return $this->getResult($class, $procedure);
} catch (\PDOException $e) { } catch (\PDOException $e) {
throw new PDOException($e, $this->config, $this->queryStr); throw new PDOException($e, $this->config, $this->queryStr);
@@ -535,7 +535,7 @@ abstract class Connection
/** /**
* 启动事务 * 启动事务
* @access public * @access public
* @return bool|null * @return void
*/ */
public function startTrans() public function startTrans()
{ {
@@ -558,7 +558,7 @@ abstract class Connection
/** /**
* 用于非自动提交状态下面的查询提交 * 用于非自动提交状态下面的查询提交
* @access public * @access public
* @return boolean * @return void
* @throws PDOException * @throws PDOException
*/ */
public function commit() public function commit()
@@ -575,7 +575,7 @@ abstract class Connection
/** /**
* 事务回滚 * 事务回滚
* @access public * @access public
* @return boolean * @return void
* @throws PDOException * @throws PDOException
*/ */
public function rollback() public function rollback()

View File

@@ -238,33 +238,33 @@ class Query
/** /**
* 启动事务 * 启动事务
* @access public * @access public
* @return bool|null * @return void
*/ */
public function startTrans() public function startTrans()
{ {
return $this->connection->startTrans(); $this->connection->startTrans();
} }
/** /**
* 用于非自动提交状态下面的查询提交 * 用于非自动提交状态下面的查询提交
* @access public * @access public
* @return boolean * @return void
* @throws PDOException * @throws PDOException
*/ */
public function commit() public function commit()
{ {
return $this->connection->commit(); $this->connection->commit();
} }
/** /**
* 事务回滚 * 事务回滚
* @access public * @access public
* @return boolean * @return void
* @throws PDOException * @throws PDOException
*/ */
public function rollback() public function rollback()
{ {
return $this->connection->rollback(); $this->connection->rollback();
} }
/** /**

View File

@@ -13,20 +13,20 @@ namespace think\exception;
class ClassNotFoundException extends \RuntimeException class ClassNotFoundException extends \RuntimeException
{ {
protected $class; protected $class;
public function __construct($message,$class='') public function __construct($message, $class = '')
{ {
$this->message = $message; $this->message = $message;
$this->class = $class; $this->class = $class;
} }
/** /**
* 获取类名 * 获取类名
* @access public * @access public
* @return string * @return string
*/ */
public function getClass() public function getClass()
{ {
return $this->class; return $this->class;
} }
} }

View File

@@ -20,24 +20,23 @@ class DbException extends Exception
{ {
/** /**
* DbException constructor. * DbException constructor.
* @param string $message * @param string $message
* @param array $config * @param array $config
* @param string $sql * @param string $sql
* @param int $code * @param int $code
*/ */
public function __construct($message, Array $config, $sql, $code = 10500) public function __construct($message, array $config, $sql, $code = 10500)
{ {
$this->message = $message; $this->message = $message;
$this->code = $code; $this->code = $code;
$this->setData('Database Status', [ $this->setData('Database Status', [
'Error Code' => $code, 'Error Code' => $code,
'Error Message' => $message, 'Error Message' => $message,
'Error SQL' => $sql 'Error SQL' => $sql,
]); ]);
$this->setData('Database Config', $config); $this->setData('Database Config', $config);
} }
} }

View File

@@ -11,7 +11,6 @@
namespace think\exception; namespace think\exception;
class HttpException extends \RuntimeException class HttpException extends \RuntimeException
{ {
private $statusCode; private $statusCode;

View File

@@ -11,7 +11,6 @@
namespace think\exception; namespace think\exception;
use think\Response; use think\Response;
class HttpResponseException extends \RuntimeException class HttpResponseException extends \RuntimeException
@@ -31,5 +30,4 @@ class HttpResponseException extends \RuntimeException
return $this->response; return $this->response;
} }
} }

View File

@@ -22,18 +22,18 @@ class PDOException extends DbException
/** /**
* PDOException constructor. * PDOException constructor.
* @param \PDOException $exception * @param \PDOException $exception
* @param array $config * @param array $config
* @param string $sql * @param string $sql
* @param int $code * @param int $code
*/ */
public function __construct(\PDOException $exception, Array $config, $sql, $code = 10501) public function __construct(\PDOException $exception, array $config, $sql, $code = 10501)
{ {
$error = $exception->errorInfo; $error = $exception->errorInfo;
$this->setData('PDO Error Info', [ $this->setData('PDO Error Info', [
'SQLSTATE' => $error[0], 'SQLSTATE' => $error[0],
'Driver Error Code' => $error[1], 'Driver Error Code' => $error[1],
'Driver Error Message' => isset($error[2]) ? $error[2] : '' 'Driver Error Message' => isset($error[2]) ? $error[2] : '',
]); ]);
parent::__construct($exception->getMessage(), $config, $sql, $code); parent::__construct($exception->getMessage(), $config, $sql, $code);

View File

@@ -13,21 +13,21 @@ namespace think\exception;
class TemplateNotFoundException extends \RuntimeException class TemplateNotFoundException extends \RuntimeException
{ {
protected $template; protected $template;
public function __construct($message,$template='') public function __construct($message, $template = '')
{ {
$this->message = $message; $this->message = $message;
$this->template = $template; $this->template = $template;
} }
/** /**
* 获取模板文件 * 获取模板文件
* @access public * @access public
* @return string * @return string
*/ */
public function getTemplate() public function getTemplate()
{ {
return $this->template; return $this->template;
} }
} }

View File

@@ -11,7 +11,6 @@
namespace think\exception; namespace think\exception;
class ThrowableError extends \ErrorException class ThrowableError extends \ErrorException
{ {
public function __construct(\Throwable $e) public function __construct(\Throwable $e)
@@ -36,7 +35,6 @@ class ThrowableError extends \ErrorException
$e->getLine() $e->getLine()
); );
$this->setTrace($e->getTrace()); $this->setTrace($e->getTrace());
} }

View File

@@ -13,20 +13,21 @@ namespace think\exception;
class ValidateException extends \RuntimeException class ValidateException extends \RuntimeException
{ {
protected $error; protected $error;
public function __construct($error) public function __construct($error)
{ {
$this->error = $error; $this->error = $error;
} $this->message = is_array($error) ? implode("\n\r", $error) : $error;
}
/** /**
* 获取验证错误信息 * 获取验证错误信息
* @access public * @access public
* @return array|string * @return array|string
*/ */
public function getError() public function getError()
{ {
return $this->error; return $this->error;
} }
} }

View File

@@ -80,12 +80,12 @@ class File
if (in_array($type, $this->config['apart_level'])) { if (in_array($type, $this->config['apart_level'])) {
// 独立记录的日志级别 // 独立记录的日志级别
$filename = $path . DS . $type . '.log'; $filename = $path . DS . $type . '.log';
error_log("[{$now}] {$server} {$remote} {$method} {$uri}\r\n{$level}\r\n", 3, $filename); error_log("[{$now}] {$server} {$remote} {$method} {$uri}\r\n{$level}\r\n---------------------------------------------------------------\r\n", 3, $filename);
} else { } else {
$info .= $level; $info .= $level;
} }
} }
return error_log("[{$now}] {$server} {$remote} {$method} {$uri}\r\n{$info}\r\n", 3, $destination); return error_log("[{$now}] {$server} {$remote} {$method} {$uri}\r\n{$info}\r\n---------------------------------------------------------------\r\n", 3, $destination);
} }
} }

View File

@@ -37,7 +37,7 @@ trait SoftDelete
public static function onlyTrashed() public static function onlyTrashed()
{ {
$model = new static(); $model = new static();
return $model->db()->where(static::$deleteTime, '>', 0); return $model->db()->where(static::$deleteTime, 'exp', 'is not null');
} }
/** /**
@@ -104,7 +104,9 @@ trait SoftDelete
{ {
if (static::$deleteTime) { if (static::$deleteTime) {
// 恢复删除 // 恢复删除
$this->setAttr(static::$deleteTime, 0); $name = static::$deleteTime;
$this->change[] = $name;
$this->data[$name] = null;
return $this->isUpdate()->save(); return $this->isUpdate()->save();
} }
return false; return false;
@@ -118,7 +120,7 @@ trait SoftDelete
protected static function base($query) protected static function base($query)
{ {
if (static::$deleteTime) { if (static::$deleteTime) {
$query->where(static::$deleteTime, 0); $query->where(static::$deleteTime, 'null');
} }
} }

View File

@@ -226,6 +226,8 @@
width: 100%; width: 100%;
margin: 12px 0; margin: 12px 0;
box-sizing: border-box; box-sizing: border-box;
table-layout:fixed;
word-wrap:break-word;
} }
.exception-var table caption{ .exception-var table caption{
text-align: left; text-align: left;
@@ -249,7 +251,7 @@
word-break: break-all; word-break: break-all;
} }
.exception-var table td:first-child{ .exception-var table td:first-child{
width: 12px; width: 28%;
font-weight: bold; font-weight: bold;
white-space: nowrap; white-space: nowrap;
} }
@@ -292,7 +294,7 @@
<div> <div>
<h2>[<?php echo $code; ?>] <?php echo sprintf('%s in %s', parse_class($name), parse_file($file, $line)); ?></h2> <h2>[<?php echo $code; ?>] <?php echo sprintf('%s in %s', parse_class($name), parse_file($file, $line)); ?></h2>
</div> </div>
<div><h1><?php echo htmlentities($message); ?></h1></div> <div><h1><?php echo nl2br(htmlentities($message)); ?></h1></div>
</div> </div>
</div> </div>