[更新]ComposerUpdate

This commit is contained in:
Anyon 2018-05-19 15:53:57 +08:00
parent d77de72c4e
commit 1316e885f8
63 changed files with 1407 additions and 938 deletions

View File

@ -28,31 +28,6 @@ if (interface_exists('Psr\Log\LoggerInterface')) {
{} {}
} }
// 注册核心类到容器
Container::getInstance()->bind([
'app' => App::class,
'build' => Build::class,
'cache' => Cache::class,
'config' => Config::class,
'cookie' => Cookie::class,
'debug' => Debug::class,
'env' => Env::class,
'hook' => Hook::class,
'lang' => Lang::class,
'log' => Log::class,
'middleware' => Middleware::class,
'request' => Request::class,
'response' => Response::class,
'route' => Route::class,
'session' => Session::class,
'url' => Url::class,
'validate' => Validate::class,
'view' => View::class,
'rule_name' => route\RuleName::class,
// 接口依赖注入
'think\LoggerInterface' => Log::class,
]);
// 注册核心类的静态代理 // 注册核心类的静态代理
Facade::bind([ Facade::bind([
facade\App::class => App::class, facade\App::class => App::class,
@ -97,9 +72,3 @@ Loader::addClassAlias([
'Validate' => facade\Validate::class, 'Validate' => facade\Validate::class,
'View' => facade\View::class, 'View' => facade\View::class,
]); ]);
// 加载惯例配置文件
facade\Config::set(include __DIR__ . '/convention.php');
// 加载composer autofile文件
Loader::loadComposerAutoloadFiles();

View File

@ -15,8 +15,8 @@ return [
'app_trace' => false, 'app_trace' => false,
// 应用模式状态 // 应用模式状态
'app_status' => '', 'app_status' => '',
// 是否支持多模块 // 是否HTTPS
'app_multi_module' => true, 'is_https' => false,
// 入口自动绑定模块 // 入口自动绑定模块
'auto_bind_module' => false, 'auto_bind_module' => false,
// 注册的根命名空间 // 注册的根命名空间
@ -33,56 +33,81 @@ return [
'default_timezone' => 'Asia/Shanghai', 'default_timezone' => 'Asia/Shanghai',
// 是否开启多语言 // 是否开启多语言
'lang_switch_on' => false, 'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个 // 默认验证器
'default_filter' => '', 'default_validate' => '',
// 默认语言 // 默认语言
'default_lang' => 'zh-cn', 'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | 模块设置 // | 模块设置
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// 自动搜索控制器
'controller_auto_search' => false,
// 操作方法前缀
'use_action_prefix' => false,
// 操作方法后缀
'action_suffix' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 默认的空模块名
'empty_module' => '',
// 默认模块名 // 默认模块名
'default_module' => 'index', 'default_module' => 'index',
// 是否支持多模块
'app_multi_module' => true,
// 禁止访问模块 // 禁止访问模块
'deny_module_list' => ['common'], 'deny_module_list' => ['common'],
// 默认控制器名 // 默认控制器名
'default_controller' => 'Index', 'default_controller' => 'Index',
// 默认操作名 // 默认操作名
'default_action' => 'index', 'default_action' => 'index',
// 默认验证器 // 是否自动转换URL中的控制器和操作名
'default_validate' => '', 'url_convert' => true,
// 默认的空模块名 // 默认的访问控制器层
'empty_module' => '', 'url_controller_layer' => 'controller',
// 默认的空控制器名 // 应用类库后缀
'empty_controller' => 'Error', 'class_suffix' => false,
// 操作方法前缀 // 控制器类后缀
'use_action_prefix' => false, 'controller_suffix' => false,
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | URL设置 // | URL请求设置
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// PATHINFO变量名 用于兼容模式 // PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's', 'var_pathinfo' => 's',
// 兼容PATH_INFO获取 // 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'], 'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// HTTPS代理标识 // HTTPS代理标识
'https_agent_name' => '', 'https_agent_name' => '',
// IP代理获取标识 // IP代理获取标识
'http_agent_ip' => 'X-REAL-IP', 'http_agent_ip' => 'X-REAL-IP',
// URL伪静态后缀 // URL伪静态后缀
'url_html_suffix' => 'html', 'url_html_suffix' => 'html',
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +----------------------------------------------------------------------
// | 路由设置
// +----------------------------------------------------------------------
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL普通方式参数 用于自动生成 // URL普通方式参数 用于自动生成
'url_common_param' => false, 'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析 // URL参数方式 0 按名称成对解析 1 按顺序解析
@ -97,36 +122,22 @@ return [
'route_complete_match' => false, 'route_complete_match' => false,
// 使用注解路由 // 使用注解路由
'route_annotation' => false, 'route_annotation' => false,
// 域名根如thinkphp.cn // 默认的路由变量规则
'url_domain_root' => '', 'default_route_pattern' => '\w+',
// 是否自动转换URL中的控制器和操作名 // 是否开启路由缓存
'url_convert' => true, 'route_check_cache' => false,
// 默认的访问控制器层 // 路由缓存的Key自定义设置闭包默认为当前URL和请求类型的md5
'url_controller_layer' => 'controller', 'route_check_cache_key' => '',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
'dispatch_error_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | 异常及错误设置 // | 异常及错误设置
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
'dispatch_error_tmpl' => __DIR__ . '/tpl/dispatch_jump.tpl',
// 异常页面的模板文件 // 异常页面的模板文件
'exception_tmpl' => __DIR__ . '/tpl/think_exception.tpl', 'exception_tmpl' => __DIR__ . '/tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效 // 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~', 'error_message' => '页面错误!请稍后再试~',
// 显示错误信息 // 显示错误信息
@ -180,6 +191,7 @@ return [
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效 // | Trace设置 开启 app_trace 后 有效
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
'trace' => [ 'trace' => [
// 内置Html Console 支持扩展 // 内置Html Console 支持扩展
'type' => 'Html', 'type' => 'Html',
@ -222,6 +234,7 @@ return [
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
// | Cookie设置 // | Cookie设置
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
'cookie' => [ 'cookie' => [
// cookie 名称前缀 // cookie 名称前缀
'prefix' => '', 'prefix' => '',

View File

@ -101,7 +101,7 @@ if (!function_exists('bind')) {
*/ */
function bind($abstract, $concrete = null) function bind($abstract, $concrete = null)
{ {
return Container::getInstance()->bind($abstract, $concrete); return Container::getInstance()->bindTo($abstract, $concrete);
} }
} }

View File

@ -18,9 +18,9 @@ use think\route\Dispatch;
/** /**
* App 应用管理 * App 应用管理
*/ */
class App implements \ArrayAccess class App extends Container
{ {
const VERSION = '5.1.13'; const VERSION = '5.1.14';
/** /**
* 当前模块路径 * 当前模块路径
@ -32,7 +32,7 @@ class App implements \ArrayAccess
* 应用调试模式 * 应用调试模式
* @var bool * @var bool
*/ */
protected $debug = true; protected $appDebug = true;
/** /**
* 应用开始时间 * 应用开始时间
@ -112,22 +112,15 @@ class App implements \ArrayAccess
*/ */
protected $dispatch; protected $dispatch;
/**
* 容器对象实例
* @var Container
*/
protected $container;
/** /**
* 绑定模块(控制器) * 绑定模块(控制器)
* @var string * @var string
*/ */
protected $bind; protected $bindModule;
public function __construct($appPath = '') public function __construct($appPath = '')
{ {
$this->appPath = $appPath ? realpath($appPath) . DIRECTORY_SEPARATOR : $this->getAppPath(); $this->appPath = $appPath ? realpath($appPath) . DIRECTORY_SEPARATOR : $this->getAppPath();
$this->container = Container::getInstance();
$this->thinkPath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; $this->thinkPath = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR;
$this->rootPath = dirname($this->appPath) . DIRECTORY_SEPARATOR; $this->rootPath = dirname($this->appPath) . DIRECTORY_SEPARATOR;
@ -144,7 +137,7 @@ class App implements \ArrayAccess
*/ */
public function bind($bind) public function bind($bind)
{ {
$this->bind = $bind; $this->bindModule = $bind;
return $this; return $this;
} }
@ -160,6 +153,39 @@ class App implements \ArrayAccess
return $this; return $this;
} }
/**
* 注册核心容器实例
* @access public
* @return void
*/
public function registerCoreContainer()
{
// 注册核心类到容器
$this->bindTo([
'app' => App::class,
'build' => Build::class,
'cache' => Cache::class,
'config' => Config::class,
'cookie' => Cookie::class,
'debug' => Debug::class,
'env' => Env::class,
'hook' => Hook::class,
'lang' => Lang::class,
'log' => Log::class,
'middleware' => Middleware::class,
'request' => Request::class,
'response' => Response::class,
'route' => Route::class,
'session' => Session::class,
'url' => Url::class,
'validate' => Validate::class,
'view' => View::class,
'rule_name' => route\RuleName::class,
// 接口依赖注入
'think\LoggerInterface' => Log::class,
]);
}
/** /**
* 初始化应用 * 初始化应用
* @access public * @access public
@ -170,6 +196,15 @@ class App implements \ArrayAccess
$this->beginTime = microtime(true); $this->beginTime = microtime(true);
$this->beginMem = memory_get_usage(); $this->beginMem = memory_get_usage();
static::setInstance($this);
$this->registerCoreContainer();
$this->instance('app', $this);
// 加载惯例配置文件
$this->config->set(include $this->thinkPath . 'convention.php');
// 设置路径环境变量 // 设置路径环境变量
$this->env->set([ $this->env->set([
'think_path' => $this->thinkPath, 'think_path' => $this->thinkPath,
@ -202,10 +237,10 @@ class App implements \ArrayAccess
$this->suffix = $this->config('app.class_suffix'); $this->suffix = $this->config('app.class_suffix');
// 应用调试模式 // 应用调试模式
$this->debug = $this->env->get('app_debug', $this->config('app.app_debug')); $this->appDebug = $this->env->get('app_debug', $this->config('app.app_debug'));
$this->env->set('app_debug', $this->debug); $this->env->set('app_debug', $this->appDebug);
if (!$this->debug) { if (!$this->appDebug) {
ini_set('display_errors', 'Off'); ini_set('display_errors', 'Off');
} elseif (PHP_SAPI != 'cli') { } elseif (PHP_SAPI != 'cli') {
//重新申请一块比较大的buffer //重新申请一块比较大的buffer
@ -218,14 +253,25 @@ class App implements \ArrayAccess
} }
} }
// 注册异常处理类
if ($this->config('app.exception_handle')) {
Error::setExceptionHandler($this->config('app.exception_handle'));
}
// 注册根命名空间 // 注册根命名空间
if (!empty($this->config('app.root_namespace'))) { if (!empty($this->config('app.root_namespace'))) {
Loader::addNamespace($this->config('app.root_namespace')); Loader::addNamespace($this->config('app.root_namespace'));
} }
// 加载composer autofile文件
Loader::loadComposerAutoloadFiles();
// 注册类库别名 // 注册类库别名
Loader::addClassAlias($this->config->pull('alias')); Loader::addClassAlias($this->config->pull('alias'));
// 数据库配置初始化
Db::init($this->config->pull('database'));
// 设置系统时区 // 设置系统时区
date_default_timezone_set($this->config('app.default_timezone')); date_default_timezone_set($this->config('app.default_timezone'));
@ -284,7 +330,7 @@ class App implements \ArrayAccess
if (is_file($path . 'provider.php')) { if (is_file($path . 'provider.php')) {
$provider = include $path . 'provider.php'; $provider = include $path . 'provider.php';
if (is_array($provider)) { if (is_array($provider)) {
$this->container->bind($provider); $this->bindTo($provider);
} }
} }
@ -307,7 +353,40 @@ class App implements \ArrayAccess
$this->setModulePath($path); $this->setModulePath($path);
$this->request->filter($this->config('app.default_filter')); if ($module) {
// 对容器中的对象实例进行配置更新
$this->containerConfigUpdate($module);
}
}
protected function containerConfigUpdate($module)
{
$config = $this->config->get();
// 注册异常处理类
if ($config['app']['exception_handle']) {
Error::setExceptionHandler($config['app']['exception_handle']);
}
Db::init($config['database']);
$this->request->init($config['app']);
$this->cookie->init($config['cookie']);
$this->view->init($config['template']);
$this->log->init($config['log']);
$this->session->setConfig($config['session']);
$this->debug->setConfig($config['trace']);
$this->cache->init($config['cache'], true);
// 加载当前模块语言包
$this->lang->load($this->appPath . $module . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $this->request->langset() . '.php');
// 模块请求缓存检查
$this->request->cache(
$config['app']['request_cache'],
$config['app']['request_cache_expire'],
$config['app']['request_cache_except']
);
} }
/** /**
@ -322,9 +401,9 @@ class App implements \ArrayAccess
// 初始化应用 // 初始化应用
$this->initialize(); $this->initialize();
if ($this->bind) { if ($this->bindModule) {
// 模块/控制器绑定 // 模块/控制器绑定
$this->route->bind($this->bind); $this->route->bind($this->bindModule);
} elseif ($this->config('app.auto_bind_module')) { } elseif ($this->config('app.auto_bind_module')) {
// 入口自动绑定 // 入口自动绑定
$name = pathinfo($this->request->baseFile(), PATHINFO_FILENAME); $name = pathinfo($this->request->baseFile(), PATHINFO_FILENAME);
@ -337,22 +416,32 @@ class App implements \ArrayAccess
$this->hook->listen('app_dispatch'); $this->hook->listen('app_dispatch');
// 获取应用调度信息 // 获取应用调度信息
if (!$this->appDebug && $this->config->get('route_check_cache')) {
$routeKey = $this->getRouteCacheKey();
if ($this->cache->has($routeKey)) {
$this->dispatch = $this->cache->get($routeKey);
}
}
$dispatch = $this->dispatch; $dispatch = $this->dispatch;
if (empty($dispatch)) { if (empty($dispatch)) {
// 路由检测 // 路由检测
$this->route
->lazy($this->config('app.url_lazy_route'))
->autoSearchController($this->config('app.controller_auto_search'))
->mergeRuleRegex($this->config('app.route_rule_merge'));
$dispatch = $this->routeCheck(); $dispatch = $this->routeCheck();
try {
if (isset($routeKey)) {
$this->cache->tag('route_cache')->set($routeKey, $dispatch);
}
} catch (\Exception $e) {}
} }
// 记录当前调度信息 // 记录当前调度信息
$this->request->dispatch($dispatch); $this->request->dispatch($dispatch);
// 记录路由和请求信息 // 记录路由和请求信息
if ($this->debug) { if ($this->appDebug) {
$this->log('[ ROUTE ] ' . var_export($this->request->routeInfo(), true)); $this->log('[ ROUTE ] ' . var_export($this->request->routeInfo(), true));
$this->log('[ HEADER ] ' . var_export($this->request->header(), true)); $this->log('[ HEADER ] ' . var_export($this->request->header(), true));
$this->log('[ PARAM ] ' . var_export($this->request->param(), true)); $this->log('[ PARAM ] ' . var_export($this->request->param(), true));
@ -363,9 +452,9 @@ class App implements \ArrayAccess
// 请求缓存检查 // 请求缓存检查
$this->request->cache( $this->request->cache(
$this->config('app.request_cache'), $this->config('request_cache'),
$this->config('app.request_cache_expire'), $this->config('request_cache_expire'),
$this->config('app.request_cache_except') $this->config('request_cache_except')
); );
$data = null; $data = null;
@ -407,10 +496,23 @@ class App implements \ArrayAccess
return $response; return $response;
} }
protected function getRouteCacheKey()
{
if ($this->config->get('route_check_cache_key')) {
$closure = $this->config->get('route_check_cache_key');
$routeKey = $closure($this->request);
} else {
$routeKey = md5($this->request->baseUrl(true) . ':' . $this->request->method());
}
return $routeKey;
}
protected function loadLangPack() protected function loadLangPack()
{ {
// 读取默认语言 // 读取默认语言
$this->lang->range($this->config('app.default_lang')); $this->lang->range($this->config('app.default_lang'));
if ($this->config('app.lang_switch_on')) { if ($this->config('app.lang_switch_on')) {
// 开启多语言机制 检测当前语言 // 开启多语言机制 检测当前语言
$this->lang->detect(); $this->lang->detect();
@ -446,7 +548,7 @@ class App implements \ArrayAccess
*/ */
public function log($msg, $type = 'info') public function log($msg, $type = 'info')
{ {
$this->debug && $this->log->record($msg, $type); $this->appDebug && $this->log->record($msg, $type);
} }
/** /**
@ -468,7 +570,6 @@ class App implements \ArrayAccess
public function routeCheck() public function routeCheck()
{ {
$path = $this->request->path(); $path = $this->request->path();
$depr = $this->config('app.pathinfo_depr');
// 路由检测 // 路由检测
$files = scandir($this->routePath); $files = scandir($this->routePath);
@ -483,10 +584,10 @@ class App implements \ArrayAccess
} }
} }
if ($this->config('app.route_annotation')) { if ($this->config('route.route_annotation')) {
// 自动生成路由定义 // 自动生成路由定义
if ($this->debug) { if ($this->appDebug) {
$this->build->buildRoute($this->config('app.controller_suffix')); $this->build->buildRoute($this->config('route.controller_suffix'));
} }
$filename = $this->runtimePath . 'build_route.php'; $filename = $this->runtimePath . 'build_route.php';
@ -501,10 +602,10 @@ class App implements \ArrayAccess
} }
// 是否强制路由模式 // 是否强制路由模式
$must = !is_null($this->routeMust) ? $this->routeMust : $this->config('app.url_route_must'); $must = !is_null($this->routeMust) ? $this->routeMust : $this->route->config('url_route_must');
// 路由检测 返回一个Dispatch对象 // 路由检测 返回一个Dispatch对象
return $this->route->check($path, $depr, $must, $this->config('app.route_complete_match')); return $this->route->check($path, $must);
} }
/** /**
@ -677,7 +778,7 @@ class App implements \ArrayAccess
} }
} }
return $this->container->invokeMethod([$class, $action . $this->config('action_suffix')], $vars); return $this->invokeMethod([$class, $action . $this->config('action_suffix')], $vars);
} }
/** /**
@ -716,7 +817,7 @@ class App implements \ArrayAccess
*/ */
public function isDebug() public function isDebug()
{ {
return $this->debug; return $this->appDebug;
} }
/** /**
@ -867,53 +968,4 @@ class App implements \ArrayAccess
return $this->beginMem; return $this->beginMem;
} }
/**
* 获取容器实例
* @access public
* @return Container
*/
public function container()
{
return $this->container;
}
public function __set($name, $value)
{
$this->container->bind($name, $value);
}
public function __get($name)
{
return $this->container->make($name);
}
public function __isset($name)
{
return $this->container->bound($name);
}
public function __unset($name)
{
$this->container->delete($name);
}
public function offsetExists($key)
{
return $this->__isset($key);
}
public function offsetGet($key)
{
return $this->__get($key);
}
public function offsetSet($key, $value)
{
$this->__set($key, $value);
}
public function offsetUnset($key)
{
$this->__unset($key);
}
} }

View File

@ -30,10 +30,10 @@ class Cache
protected $instance = []; protected $instance = [];
/** /**
* 应用对象 * 缓存配置
* @var App * @var array
*/ */
protected $app; protected $config = [];
/** /**
* 操作句柄 * 操作句柄
@ -41,9 +41,10 @@ class Cache
*/ */
protected $handler; protected $handler;
public function __construct(App $app) public function __construct(array $config = [])
{ {
$this->app = $app; $this->config = $config;
$this->init($config);
} }
/** /**
@ -55,23 +56,18 @@ class Cache
*/ */
public function connect(array $options = [], $name = false) public function connect(array $options = [], $name = false)
{ {
$type = !empty($options['type']) ? $options['type'] : 'File';
if (false === $name) { if (false === $name) {
$name = md5(serialize($options)); $name = md5(serialize($options));
} }
if (true === $name || !isset($this->instance[$name])) { if (true === $name || !isset($this->instance[$name])) {
$class = false !== strpos($type, '\\') ? $type : '\\think\\cache\\driver\\' . ucwords($type); $type = !empty($options['type']) ? $options['type'] : 'File';
// 记录初始化信息
$this->app->log('[ CACHE ] INIT ' . $type);
if (true === $name) { if (true === $name) {
$name = md5(serialize($options)); $name = md5(serialize($options));
} }
$this->instance[$name] = new $class($options); $this->instance[$name] = Loader::factory($type, '\\think\\cache\\driver\\', $options);
} }
return $this->instance[$name]; return $this->instance[$name];
@ -81,19 +77,16 @@ class Cache
* 自动初始化缓存 * 自动初始化缓存
* @access public * @access public
* @param array $options 配置数组 * @param array $options 配置数组
* @param bool $force 强制更新
* @return Driver * @return Driver
*/ */
public function init(array $options = []) public function init(array $options = [], $force = false)
{ {
if (is_null($this->handler)) { if (is_null($this->handler) || $force) {
// 自动初始化缓存
$config = $this->app['config'];
if (empty($options) && 'complex' == $config->get('cache.type')) { if ('complex' == $options['type']) {
$default = $config->get('cache.default'); $default = $options['default'];
$options = $config->get('cache.' . $default['type']) ?: $default; $options = isset($options[$default['type']]) ? $options[$default['type']] : $default;
} elseif (empty($options)) {
$options = $config->pull('cache');
} }
$this->handler = $this->connect($options); $this->handler = $this->connect($options);
@ -102,6 +95,16 @@ class Cache
return $this->handler; return $this->handler;
} }
public static function __make(Config $config)
{
return new static($config->pull('cache'));
}
public function setConfig(array $config)
{
$this->config = array_merge($this->config, $config);
}
/** /**
* 切换缓存类型 需要配置 cache.type complex * 切换缓存类型 需要配置 cache.type complex
* @access public * @access public
@ -110,8 +113,8 @@ class Cache
*/ */
public function store($name = '') public function store($name = '')
{ {
if ('' !== $name && 'complex' == $this->app['config']->get('cache.type')) { if ('' !== $name && 'complex' == $this->config['type']) {
return $this->connect($this->app['config']->get('cache.' . $name), strtolower($name)); return $this->connect($this->config[$name], strtolower($name));
} }
return $this->init(); return $this->init();

View File

@ -20,11 +20,22 @@ class Config implements \ArrayAccess
private $config = []; private $config = [];
/** /**
* 缓存前缀 * 配置前缀
* @var string * @var string
*/ */
private $prefix = 'app'; private $prefix = 'app';
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/** /**
* 设置配置参数默认前缀 * 设置配置参数默认前缀
* @access public * @access public
@ -50,9 +61,9 @@ class Config implements \ArrayAccess
$type = pathinfo($config, PATHINFO_EXTENSION); $type = pathinfo($config, PATHINFO_EXTENSION);
} }
$class = false !== strpos($type, '\\') ? $type : '\\think\\config\\driver\\' . ucwords($type); $object = Loader::factory($type, '\\think\\config\\driver\\', $config);
return $this->set((new $class())->parse($config), $name); return $this->set($object->parse(), $name);
} }
/** /**
@ -88,15 +99,14 @@ class Config implements \ArrayAccess
protected function autoLoad($name) protected function autoLoad($name)
{ {
// 如果尚未载入 则动态加载配置文件 // 如果尚未载入 则动态加载配置文件
$module = Container::get('request')->module(); $module = $this->app->request->module();
$module = $module ? $module . DIRECTORY_SEPARATOR : ''; $module = $module ? $module . DIRECTORY_SEPARATOR : '';
$app = Container::get('app'); $path = $this->app->getAppPath() . $module;
$path = $app->getAppPath() . $module;
if (is_dir($path . 'config')) { if (is_dir($path . 'config')) {
$file = $path . 'config' . DIRECTORY_SEPARATOR . $name . $app->getConfigExt(); $file = $path . 'config' . DIRECTORY_SEPARATOR . $name . $this->app->getConfigExt();
} elseif (is_dir($app->getConfigPath() . $module)) { } elseif (is_dir($this->app->getConfigPath() . $module)) {
$file = $app->getConfigPath() . $module . $name . $app->getConfigExt(); $file = $this->app->getConfigPath() . $module . $name . $this->app->getConfigExt();
} }
if (isset($file) && is_file($file)) { if (isset($file) && is_file($file)) {

View File

@ -19,7 +19,7 @@ use ReflectionFunction;
use ReflectionMethod; use ReflectionMethod;
use think\exception\ClassNotFoundException; use think\exception\ClassNotFoundException;
class Container class Container implements \ArrayAccess
{ {
/** /**
* 容器对象实例 * 容器对象实例
@ -37,7 +37,14 @@ class Container
* 容器绑定标识 * 容器绑定标识
* @var array * @var array
*/ */
protected $bind = []; protected $bind = [
'app' => 'think\App',
'config' => 'think\Config',
'lang' => 'think\Lang',
'log' => 'think\Log',
'request' => 'think\Request',
'response' => 'think\Response',
];
/** /**
* 容器标识别名 * 容器标识别名
@ -59,6 +66,17 @@ class Container
return static::$instance; return static::$instance;
} }
/**
* 设置当前容器的实例
* @access public
* @param object $instance
* @return void
*/
public static function setInstance($instance)
{
static::$instance = $instance;
}
/** /**
* 获取容器中的对象实例 * 获取容器中的对象实例
* @access public * @access public
@ -81,7 +99,7 @@ class Container
*/ */
public static function set($abstract, $concrete = null) public static function set($abstract, $concrete = null)
{ {
return static::getInstance()->bind($abstract, $concrete); return static::getInstance()->bindTo($abstract, $concrete);
} }
/** /**
@ -112,7 +130,7 @@ class Container
* @param mixed $concrete 要绑定的类、闭包或者实例 * @param mixed $concrete 要绑定的类、闭包或者实例
* @return $this * @return $this
*/ */
public function bind($abstract, $concrete = null) public function bindTo($abstract, $concrete = null)
{ {
if (is_array($abstract)) { if (is_array($abstract)) {
$this->bind = array_merge($this->bind, $abstract); $this->bind = array_merge($this->bind, $abstract);
@ -378,8 +396,7 @@ class Container
$class = $param->getClass(); $class = $param->getClass();
if ($class) { if ($class) {
$className = $class->getName(); $args[] = $this->getObjectParam($class->getName(), $vars);
$args[] = $this->make($className);
} elseif (1 == $type && !empty($vars)) { } elseif (1 == $type && !empty($vars)) {
$args[] = array_shift($vars); $args[] = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) { } elseif (0 == $type && isset($vars[$name])) {
@ -394,4 +411,64 @@ class Container
return $args; return $args;
} }
/**
* 获取对象类型的参数值
* @access protected
* @param string $className 类名
* @param array $vars 参数
* @return mixed
*/
protected function getObjectParam($className, &$vars)
{
$value = array_shift($vars);
if ($value instanceof $className) {
$result = $value;
} else {
array_unshift($vars, $value);
$result = $this->make($className);
}
return $result;
}
public function __set($name, $value)
{
$this->bindTo($name, $value);
}
public function __get($name)
{
return $this->make($name);
}
public function __isset($name)
{
return $this->bound($name);
}
public function __unset($name)
{
$this->delete($name);
}
public function offsetExists($key)
{
return $this->__isset($key);
}
public function offsetGet($key)
{
return $this->__get($key);
}
public function offsetSet($key, $value)
{
$this->__set($key, $value);
}
public function offsetUnset($key)
{
$this->__unset($key);
}
} }

View File

@ -30,12 +30,6 @@ class Controller
*/ */
protected $request; protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/** /**
* 验证失败是否抛出异常 * 验证失败是否抛出异常
* @var bool * @var bool
@ -58,13 +52,11 @@ class Controller
* 构造方法 * 构造方法
* @access public * @access public
*/ */
public function __construct() public function __construct(App $app = null)
{ {
$this->request = Container::get('request'); $this->app = $app ?: Container::get('app');
$this->app = Container::get('app'); $this->request = $this->app['request'];
$this->view = Container::get('view')->init( $this->view = $this->app['view'];
$this->app['config']->pull('template')
);
// 控制器初始化 // 控制器初始化
$this->initialize(); $this->initialize();

View File

@ -35,10 +35,13 @@ class Cookie
]; ];
/** /**
* 是否初始化 * 构造方法
* @var bool * @access public
*/ */
protected $init; public function __construct(array $config = [])
{
$this->init($config);
}
/** /**
* Cookie初始化 * Cookie初始化
@ -48,17 +51,16 @@ class Cookie
*/ */
public function init(array $config = []) public function init(array $config = [])
{ {
if (empty($config)) {
$config = Container::get('config')->pull('cookie');
}
$this->config = array_merge($this->config, array_change_key_case($config)); $this->config = array_merge($this->config, array_change_key_case($config));
if (!empty($this->config['httponly'])) { if (!empty($this->config['httponly'])) {
ini_set('session.cookie_httponly', 1); ini_set('session.cookie_httponly', 1);
} }
}
$this->init = true; public static function __make(Config $config)
{
return new static($config->pull('cookie'));
} }
/** /**
@ -87,8 +89,6 @@ class Cookie
*/ */
public function set($name, $value = '', $option = null) public function set($name, $value = '', $option = null)
{ {
!isset($this->init) && $this->init();
// 参数设置(会覆盖黙认设置) // 参数设置(会覆盖黙认设置)
if (!is_null($option)) { if (!is_null($option)) {
if (is_numeric($option)) { if (is_numeric($option)) {
@ -147,8 +147,6 @@ class Cookie
*/ */
public function has($name, $prefix = null) public function has($name, $prefix = null)
{ {
!isset($this->init) && $this->init();
$prefix = !is_null($prefix) ? $prefix : $this->config['prefix']; $prefix = !is_null($prefix) ? $prefix : $this->config['prefix'];
$name = $prefix . $name; $name = $prefix . $name;
@ -164,8 +162,6 @@ class Cookie
*/ */
public function get($name = '', $prefix = null) public function get($name = '', $prefix = null)
{ {
!isset($this->init) && $this->init();
$prefix = !is_null($prefix) ? $prefix : $this->config['prefix']; $prefix = !is_null($prefix) ? $prefix : $this->config['prefix'];
$key = $prefix . $name; $key = $prefix . $name;
@ -204,8 +200,6 @@ class Cookie
*/ */
public function delete($name, $prefix = null) public function delete($name, $prefix = null)
{ {
!isset($this->init) && $this->init();
$config = $this->config; $config = $this->config;
$prefix = !is_null($prefix) ? $prefix : $config['prefix']; $prefix = !is_null($prefix) ? $prefix : $config['prefix'];
$name = $prefix . $name; $name = $prefix . $name;
@ -231,8 +225,6 @@ class Cookie
return; return;
} }
!isset($this->init) && $this->init();
// 要删除的cookie前缀不指定则删除config设置的指定前缀 // 要删除的cookie前缀不指定则删除config设置的指定前缀
$config = $this->config; $config = $this->config;
$prefix = !is_null($prefix) ? $prefix : $config['prefix']; $prefix = !is_null($prefix) ? $prefix : $config['prefix'];

View File

@ -11,6 +11,8 @@
namespace think; namespace think;
use think\db\Connection;
/** /**
* Class Db * Class Db
* @package think * @package think
@ -57,6 +59,18 @@ namespace think;
*/ */
class Db class Db
{ {
/**
* 当前数据库连接对象
* @var Connection
*/
protected static $connection;
/**
* 数据库配置
* @var array
*/
protected static $config = [];
/** /**
* 查询次数 * 查询次数
* @var integer * @var integer
@ -69,12 +83,108 @@ class Db
*/ */
public static $executeTimes = 0; public static $executeTimes = 0;
/**
* 配置
* @access public
* @param mixed $config
* @return void
*/
public static function init($config = [])
{
self::$config = $config;
if (empty($config['query'])) {
self::$config['query'] = '\\think\\db\\Query';
}
}
/**
* 获取数据库配置
* @access public
* @return array
*/
public static function getConfig()
{
return self::$config;
}
/**
* 切换数据库连接
* @access public
* @param mixed $config 连接配置
* @param bool|string $name 连接标识 true 强制重新连接
* @param string $query 查询对象类名
* @return mixed 返回查询对象实例
* @throws Exception
*/
public static function connect($config = [], $name = false, $query = '')
{
// 解析配置参数
$options = self::parseConfig($config ?: self::$config);
$query = $query ?: self::$config['query'];
// 创建数据库连接对象实例
self::$connection = Connection::instance($options, $name);
return new $query(self::$connection);
}
/**
* 数据库连接参数解析
* @access private
* @param mixed $config
* @return array
*/
private static function parseConfig($config)
{
if (is_string($config) && false === strpos($config, '/')) {
// 支持读取配置参数
$config = isset(self::$config[$config]) ? self::$config[$config] : self::$config;
}
if (is_string($config)) {
return self::parseDsnConfig($config);
} else {
return $config;
}
}
/**
* DSN解析
* 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1&param2=val2#utf8
* @access private
* @param string $dsnStr
* @return array
*/
private static function parseDsnConfig($dsnStr)
{
$info = parse_url($dsnStr);
if (!$info) {
return [];
}
$dsn = [
'type' => $info['scheme'],
'username' => isset($info['user']) ? $info['user'] : '',
'password' => isset($info['pass']) ? $info['pass'] : '',
'hostname' => isset($info['host']) ? $info['host'] : '',
'hostport' => isset($info['port']) ? $info['port'] : '',
'database' => !empty($info['path']) ? ltrim($info['path'], '/') : '',
'charset' => isset($info['fragment']) ? $info['fragment'] : 'utf8',
];
if (isset($info['query'])) {
parse_str($info['query'], $dsn['params']);
} else {
$dsn['params'] = [];
}
return $dsn;
}
public static function __callStatic($method, $args) public static function __callStatic($method, $args)
{ {
$class = Container::get('config')->get('database.query') ?: '\\think\\db\\Query'; return call_user_func_array([static::connect(), $method], $args);
$query = new $class();
return call_user_func_array([$query, $method], $args);
} }
} }

View File

@ -11,12 +11,17 @@
namespace think; namespace think;
use think\exception\ClassNotFoundException;
use think\model\Collection as ModelCollection; use think\model\Collection as ModelCollection;
use think\response\Redirect; use think\response\Redirect;
class Debug class Debug
{ {
/**
* 配置参数
* @var array
*/
protected $config = [];
/** /**
* 区间时间信息 * 区间时间信息
* @var array * @var array
@ -35,9 +40,20 @@ class Debug
*/ */
protected $app; protected $app;
public function __construct(App $app) public function __construct(App $app, array $config = [])
{ {
$this->app = $app; $this->app = $app;
$this->config = $config;
}
public static function __make(App $app, Config $config)
{
return new static($app, $config->pull('trace'));
}
public function setConfig(array $config)
{
$this->config = array_merge($this->config, $config);
} }
/** /**
@ -221,7 +237,7 @@ class Debug
$output = '<pre>' . $label . $output . '</pre>'; $output = '<pre>' . $label . $output . '</pre>';
} }
if ($echo) { if ($echo) {
echo($output); echo ($output);
return; return;
} }
return $output; return $output;
@ -229,16 +245,12 @@ class Debug
public function inject(Response $response, &$content) public function inject(Response $response, &$content)
{ {
$config = $this->app['config']->pull('trace'); $config = $this->config;
$type = isset($config['type']) ? $config['type'] : 'Html'; $type = isset($config['type']) ? $config['type'] : 'Html';
$class = false !== strpos($type, '\\') ? $type : '\\think\\debug\\' . ucwords($type);
unset($config['type']); unset($config['type']);
if (class_exists($class)) { $trace = Loader::factory($type, '\\think\\debug\\', $config);
$trace = new $class($config);
} else {
throw new ClassNotFoundException('class not exists:' . $class, $class);
}
if ($response instanceof Redirect) { if ($response instanceof Redirect) {
//TODO 记录 //TODO 记录

View File

@ -18,6 +18,12 @@ use think\exception\ThrowableError;
class Error class Error
{ {
/**
* 配置参数
* @var array
*/
protected static $exceptionHandler;
/** /**
* 注册异常处理 * 注册异常处理
* @access public * @access public
@ -100,6 +106,18 @@ class Error
return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]); return in_array($type, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE]);
} }
/**
* 设置异常处理类
*
* @access public
* @param mixed $handle
* @return void
*/
public static function setExceptionHandler($handle)
{
self::$exceptionHandler = $handle;
}
/** /**
* Get an instance of the exception handler. * Get an instance of the exception handler.
* *
@ -112,7 +130,8 @@ class Error
if (!$handle) { if (!$handle) {
// 异常处理handle // 异常处理handle
$class = Container::get('config')->get('exception_handle'); $class = self::$exceptionHandler;
if ($class && is_string($class) && class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) { if ($class && is_string($class) && class_exists($class) && is_subclass_of($class, "\\think\\exception\\Handle")) {
$handle = new $class; $handle = new $class;
} else { } else {

View File

@ -85,15 +85,13 @@ class Facade
/** /**
* 带参数实例化当前Facade类 * 带参数实例化当前Facade类
* @access public * @access public
* @return object * @return mixed
*/ */
public static function instance(...$args) public static function instance(...$args)
{ {
if (__CLASS__ != static::class) { if (__CLASS__ != static::class) {
return self::__callStatic('instance', $args); return self::createFacade('', $args);
} }
return self::createFacade('', $args);
} }
/** /**
@ -102,7 +100,7 @@ class Facade
* @param string $class 类名或者标识 * @param string $class 类名或者标识
* @param array|true $args 变量 * @param array|true $args 变量
* @param bool $newInstance 是否每次创建新的实例 * @param bool $newInstance 是否每次创建新的实例
* @return object * @return mixed
*/ */
public static function make($class, $args = [], $newInstance = false) public static function make($class, $args = [], $newInstance = false)
{ {

View File

@ -31,6 +31,17 @@ class Hook
*/ */
private static $portal = 'run'; private static $portal = 'run';
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
/** /**
* 指定入口方法名称 * 指定入口方法名称
* @access public * @access public
@ -163,7 +174,7 @@ class Hook
$method = [$class, self::$portal]; $method = [$class, self::$portal];
} }
return Container::getInstance()->invoke($method, [$params]); return $this->app->invoke($method, [$params]);
} }
/** /**
@ -176,9 +187,7 @@ class Hook
*/ */
protected function execTag($class, $tag = '', $params = null) protected function execTag($class, $tag = '', $params = null)
{ {
$app = Container::get('app'); $this->app->isDebug() && $this->app['debug']->remark('behavior_start', 'time');
$app->isDebug() && $app['debug']->remark('behavior_start', 'time');
$method = Loader::parseName($tag, 1, false); $method = Loader::parseName($tag, 1, false);
@ -198,12 +207,12 @@ class Hook
$class = $class . '->' . $method; $class = $class . '->' . $method;
} }
$result = Container::getInstance()->invoke($call, [$params]); $result = $this->app->invoke($call, [$params]);
if ($app->isDebug()) { if ($this->app->isDebug()) {
$debug = $app['debug']; $debug = $this->app['debug'];
$debug->remark('behavior_end', 'time'); $debug->remark('behavior_end', 'time');
$app->log('[ BEHAVIOR ] Run ' . $class . ' @' . $tag . ' [ RunTime:' . $debug->getRangeTime('behavior_start', 'behavior_end') . 's ]'); $this->app->log('[ BEHAVIOR ] Run ' . $class . ' @' . $tag . ' [ RunTime:' . $debug->getRangeTime('behavior_start', 'behavior_end') . 's ]');
} }
return $result; return $result;

View File

@ -51,6 +51,17 @@ class Lang
'zh-hans-cn' => 'zh-cn', 'zh-hans-cn' => 'zh-cn',
]; ];
/**
* 应用对象
* @var App
*/
protected $app;
public function __construct(App $app)
{
$this->app = $app;
}
// 设定当前的语言 // 设定当前的语言
public function range($range = '') public function range($range = '')
{ {
@ -108,7 +119,7 @@ class Lang
foreach ($file as $_file) { foreach ($file as $_file) {
if (is_file($_file)) { if (is_file($_file)) {
// 记录加载信息 // 记录加载信息
Container::get('app')->log('[ LANG ] ' . $_file); $this->app->log('[ LANG ] ' . $_file);
$_lang = include $_file; $_lang = include $_file;
if (is_array($_lang)) { if (is_array($_lang)) {
$lang = array_change_key_case($_lang) + $lang; $lang = array_change_key_case($_lang) + $lang;
@ -200,11 +211,8 @@ class Lang
} elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { } elseif (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
// 自动侦测浏览器语言 // 自动侦测浏览器语言
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches); preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
$langSet = strtolower($matches[1]); $langSet = strtolower($matches[1]);
$acceptLangs = Container::get('config')->get('header_accept_lang'); if (isset($this->acceptLanguage[$langSet])) {
if (isset($acceptLangs[$langSet])) {
$langSet = $acceptLangs[$langSet];
} elseif (isset($this->acceptLanguage[$langSet])) {
$langSet = $this->acceptLanguage[$langSet]; $langSet = $this->acceptLanguage[$langSet];
} }
} }
@ -258,8 +266,19 @@ class Lang
* @param array $list 语言列表 * @param array $list 语言列表
* @return void * @return void
*/ */
public function setAllowLangList($list) public function setAllowLangList(array $list)
{ {
$this->allowLangList = $list; $this->allowLangList = $list;
} }
/**
* 设置转义的语言列表
* @access public
* @param array $list 语言列表
* @return void
*/
public function setAcceptLanguage(array $list)
{
$this->acceptLanguage = array_merge($this->acceptLanguage, $list);
}
} }

View File

@ -11,6 +11,8 @@
namespace think; namespace think;
use think\exception\ClassNotFoundException;
class Loader class Loader
{ {
/** /**
@ -378,6 +380,24 @@ class Loader
return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
} }
/**
* 创建工厂对象实例
* @access public
* @param string $name 工厂类名
* @param string $namespace 默认命名空间
* @return mixed
*/
public static function factory($name, $namespace = '', ...$args)
{
$class = false !== strpos($name, '\\') ? $name : $namespace . ucwords($name);
if (class_exists($class)) {
return Container::getInstance()->invokeClass($class, $args);
} else {
throw new ClassNotFoundException('class not exists:' . $class, $class);
}
}
} }
/** /**

View File

@ -11,8 +11,6 @@
namespace think; namespace think;
use think\exception\ClassNotFoundException;
class Log implements LoggerInterface class Log implements LoggerInterface
{ {
const EMERGENCY = 'emergency'; const EMERGENCY = 'emergency';
@ -66,6 +64,11 @@ class Log implements LoggerInterface
$this->app = $app; $this->app = $app;
} }
public static function __make(App $app, Config $config)
{
return (new static($app))->init($config->pull('log'));
}
/** /**
* 日志初始化 * 日志初始化
* @access public * @access public
@ -74,24 +77,17 @@ class Log implements LoggerInterface
*/ */
public function init($config = []) public function init($config = [])
{ {
$type = isset($config['type']) ? $config['type'] : 'File'; $type = isset($config['type']) ? $config['type'] : 'File';
$class = false !== strpos($type, '\\') ? $type : '\\think\\log\\driver\\' . ucwords($type);
$this->config = $config; $this->config = $config;
unset($config['type']); unset($config['type']);
if (!empty($config['close'])) { if (!empty($config['close'])) {
$this->allowWrite = false; $this->allowWrite = false;
} }
if (class_exists($class)) { $this->driver = Loader::factory($type, '\\think\\log\\driver\\', $config);
$this->driver = new $class($config);
} else {
throw new ClassNotFoundException('class not exists:' . $class, $class);
}
// 记录初始化信息
$this->app->isDebug() && $this->record('[ LOG ] INIT ' . $type);
return $this; return $this;
} }
@ -200,14 +196,10 @@ class Log implements LoggerInterface
*/ */
public function save() public function save()
{ {
if (empty($this->log) || !$this->allowWrite) { if (empty($this->log) || !$this->allowWrite || !$this->driver) {
return true; return true;
} }
if (is_null($this->driver)) {
$this->init($this->app['config']->pull('log'));
}
if (!$this->check($this->config)) { if (!$this->check($this->config)) {
// 检测日志写入权限 // 检测日志写入权限
return false; return false;
@ -261,10 +253,6 @@ class Log implements LoggerInterface
// 监听log_write // 监听log_write
$this->app['hook']->listen('log_write', $log); $this->app['hook']->listen('log_write', $log);
if (is_null($this->driver)) {
$this->init($this->app['config']->pull('log'));
}
// 写入日志 // 写入日志
$result = $this->driver->save($log); $result = $this->driver->save($log);

View File

@ -18,6 +18,26 @@ use think\exception\HttpResponseException;
class Middleware class Middleware
{ {
protected $queue = []; protected $queue = [];
protected $app;
protected $config = [
'default_namespace' => 'app\\http\\middleware\\',
];
public function __construct(App $app, array $config = [])
{
$this->app = $app;
$this->config = array_merge($this->config, $config);
}
public static function __make(App $app, Config $config)
{
return new static($app, $config->pull('middleware'));
}
public function setConfig(array $config)
{
$this->config = array_merge($this->config, $config);
}
public function import(array $middlewares = []) public function import(array $middlewares = [])
{ {
@ -89,8 +109,11 @@ class Middleware
} }
if (false === strpos($middleware, '\\')) { if (false === strpos($middleware, '\\')) {
$value = Container::get('config')->get('middleware.' . $middleware); if (isset($this->config[$middleware])) {
$middleware = $value ?: Container::get('app')->getNamespace() . '\\http\\middleware\\' . $middleware; $middleware = $this->config[$middleware];
} else {
$middleware = $this->config['default_namespace'] . $middleware;
}
} }
if (is_array($middleware)) { if (is_array($middleware)) {
@ -101,7 +124,7 @@ class Middleware
list($middleware, $param) = explode(':', $middleware, 2); list($middleware, $param) = explode(':', $middleware, 2);
} }
return [[Container::get($middleware), 'handle'], isset($param) ? $param : null]; return [[$this->app->make($middleware), 'handle'], isset($param) ? $param : null];
} }
protected function resolve() protected function resolve()

View File

@ -32,6 +32,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
*/ */
private $isUpdate = false; private $isUpdate = false;
/**
* 是否Replace
* @var bool
*/
private $replace = false;
/** /**
* 是否强制更新所有数据 * 是否强制更新所有数据
* @var bool * @var bool
@ -141,13 +147,13 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 记录原始数据 // 记录原始数据
$this->origin = $this->data; $this->origin = $this->data;
$config = Container::get('config'); $config = Db::getConfig();
if (empty($this->name)) { if (empty($this->name)) {
// 当前模型名 // 当前模型名
$name = str_replace('\\', '/', static::class); $name = str_replace('\\', '/', static::class);
$this->name = basename($name); $this->name = basename($name);
if ($config->get('class_suffix')) { if (Container::get('config')->get('class_suffix')) {
$suffix = basename(dirname($name)); $suffix = basename(dirname($name));
$this->name = substr($this->name, 0, -strlen($suffix)); $this->name = substr($this->name, 0, -strlen($suffix));
} }
@ -155,26 +161,26 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (is_null($this->autoWriteTimestamp)) { if (is_null($this->autoWriteTimestamp)) {
// 自动写入时间戳 // 自动写入时间戳
$this->autoWriteTimestamp = $config->get('database.auto_timestamp'); $this->autoWriteTimestamp = $config['auto_timestamp'];
} }
if (is_null($this->dateFormat)) { if (is_null($this->dateFormat)) {
// 设置时间戳格式 // 设置时间戳格式
$this->dateFormat = $config->get('database.datetime_format'); $this->dateFormat = $config['datetime_format'];
} }
if (is_null($this->resultSetType)) { if (is_null($this->resultSetType)) {
$this->resultSetType = $config->get('database.resultset_type'); $this->resultSetType = $config['resultset_type'];
} }
if (is_null($this->query)) { if (is_null($this->query)) {
// 设置查询对象 // 设置查询对象
$this->query = $config->get('database.query'); $this->query = $config['query'];
} }
if (!empty($this->connection) && is_array($this->connection)) { if (!empty($this->connection) && is_array($this->connection)) {
// 设置模型的数据库连接 // 设置模型的数据库连接
$this->connection = array_merge($config->pull('database'), $this->connection); $this->connection = array_merge($config, $this->connection);
} }
if ($this->observerClass) { if ($this->observerClass) {
@ -232,9 +238,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
protected function buildQuery() protected function buildQuery()
{ {
// 设置当前模型 确保查询返回模型对象 // 设置当前模型 确保查询返回模型对象
$class = $this->query; $query = Db::connect($this->connection, false, $this->query);
$query = (new $class())->connect($this->connection) $query->model($this)
->model($this)
->json($this->json) ->json($this->json)
->setJsonFieldType($this->jsonType); ->setJsonFieldType($this->jsonType);
@ -355,6 +360,18 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
return $this; return $this;
} }
/**
* 新增数据是否使用Replace
* @access public
* @param bool $replace
* @return $this
*/
public function replace($replace = true)
{
$this->replace = $replace;
return $this;
}
/** /**
* 保存当前数据对象 * 保存当前数据对象
* @access public * @access public
@ -559,7 +576,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 检查允许字段 // 检查允许字段
$allowFields = $this->checkAllowFields(array_merge($this->auto, $this->insert)); $allowFields = $this->checkAllowFields(array_merge($this->auto, $this->insert));
$result = $this->db(false)->strict(false)->field($allowFields)->insert($this->data, false, false, $sequence); $result = $this->db(false)->strict(false)->field($allowFields)->insert($this->data, $this->replace, false, $sequence);
// 获取自动增长主键 // 获取自动增长主键
if ($result && $insertId = $this->db(false)->getLastInsID($sequence)) { if ($result && $insertId = $this->db(false)->getLastInsID($sequence)) {
@ -780,9 +797,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* @access public * @access public
* @param array $data 数据数组 * @param array $data 数据数组
* @param array|true $field 允许字段 * @param array|true $field 允许字段
* @param bool $replace 使用Replace
* @return static * @return static
*/ */
public static function create($data = [], $field = null) public static function create($data = [], $field = null, $replace = false)
{ {
$model = new static(); $model = new static();
@ -790,7 +808,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$model->allowField($field); $model->allowField($field);
} }
$model->isUpdate(false)->save($data, []); $model->isUpdate(false)->replace($replace)->save($data, []);
return $model; return $model;
} }

View File

@ -22,10 +22,16 @@ class Request
protected $instance; protected $instance;
/** /**
* 配置对象 * 应用对象实例
* @var Config * @var App
*/ */
protected $config; protected $app;
/**
* 配置参数
* @var array
*/
protected $config = [];
/** /**
* 请求类型 * 请求类型
@ -262,24 +268,37 @@ class Request
* @access public * @access public
* @param array $options 参数 * @param array $options 参数
*/ */
public function __construct($options = []) public function __construct(App $app, array $options = [])
{ {
foreach ($options as $name => $item) { $this->app = $app;
if (property_exists($this, $name)) { $this->init($options);
$this->$name = $item;
}
}
$this->config = Container::get('config');
if (is_null($this->filter)) {
$this->filter = $this->config->get('default_filter');
}
// 保存 php://input // 保存 php://input
$this->input = file_get_contents('php://input'); $this->input = file_get_contents('php://input');
} }
public function init(array $options = [])
{
$this->config = array_merge($this->config, $options);
if (is_null($this->filter) && !empty($this->config['default_filter'])) {
$this->filter = $this->config['default_filter'];
}
}
public function config($name = null)
{
if (is_null($name)) {
return $this->config;
}
return isset($this->config[$name]) ? $this->config[$name] : null;
}
public static function __make(App $app, Config $config)
{
return new static($app, $config->pull('app'));
}
public function __call($method, $args) public function __call($method, $args)
{ {
if (array_key_exists($method, $this->hook)) { if (array_key_exists($method, $this->hook)) {
@ -431,7 +450,7 @@ class Request
*/ */
public function rootDomain() public function rootDomain()
{ {
$root = $this->config->get('app.url_domain_root'); $root = $this->config['url_domain_root'];
if (!$root) { if (!$root) {
$item = explode('.', $this->host(true)); $item = explode('.', $this->host(true));
@ -451,7 +470,7 @@ class Request
{ {
if (is_null($this->subDomain)) { if (is_null($this->subDomain)) {
// 获取当前主域名 // 获取当前主域名
$rootDomain = $this->config->get('app.url_domain_root'); $rootDomain = $this->config['url_domain_root'];
if ($rootDomain) { if ($rootDomain) {
// 配置域名根 例如 thinkphp.cn 163.com.cn 如果是国家级域名 com.cn net.cn 之类的域名需要配置 // 配置域名根 例如 thinkphp.cn 163.com.cn 如果是国家级域名 com.cn net.cn 之类的域名需要配置
@ -609,10 +628,10 @@ class Request
public function pathinfo() public function pathinfo()
{ {
if (is_null($this->pathinfo)) { if (is_null($this->pathinfo)) {
if (isset($_GET[$this->config->get('var_pathinfo')])) { if (isset($_GET[$this->config['var_pathinfo']])) {
// 判断URL里面是否有兼容模式参数 // 判断URL里面是否有兼容模式参数
$_SERVER['PATH_INFO'] = $_GET[$this->config->get('var_pathinfo')]; $_SERVER['PATH_INFO'] = $_GET[$this->config['var_pathinfo']];
unset($_GET[$this->config->get('var_pathinfo')]); unset($_GET[$this->config['var_pathinfo']]);
} elseif ($this->isCli()) { } elseif ($this->isCli()) {
// CLI模式下 index.php module/controller/action/params/... // CLI模式下 index.php module/controller/action/params/...
$_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
@ -622,7 +641,7 @@ class Request
// 分析PATHINFO信息 // 分析PATHINFO信息
if (!isset($_SERVER['PATH_INFO'])) { if (!isset($_SERVER['PATH_INFO'])) {
foreach ($this->config->get('pathinfo_fetch') as $type) { foreach ($this->config['pathinfo_fetch'] as $type) {
if (!empty($_SERVER[$type])) { if (!empty($_SERVER[$type])) {
$_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ? $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
@ -645,7 +664,7 @@ class Request
public function path() public function path()
{ {
if (is_null($this->path)) { if (is_null($this->path)) {
$suffix = $this->config->get('url_html_suffix'); $suffix = $this->config['url_html_suffix'];
$pathinfo = $this->pathinfo(); $pathinfo = $this->pathinfo();
if (false === $suffix) { if (false === $suffix) {
// 禁止伪静态访问 // 禁止伪静态访问
@ -736,8 +755,8 @@ class Request
// 获取原始请求类型 // 获取原始请求类型
return $this->isCli() ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']); return $this->isCli() ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']);
} elseif (!$this->method) { } elseif (!$this->method) {
if (isset($_POST[$this->config->get('var_method')])) { if (isset($_POST[$this->config['var_method']])) {
$this->method = strtoupper($_POST[$this->config->get('var_method')]); $this->method = strtoupper($_POST[$this->config['var_method']]);
$this->{$this->method}($_POST); $this->{$this->method}($_POST);
} elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) {
$this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']);
@ -1033,7 +1052,7 @@ class Request
public function session($name = '', $default = null, $filter = '') public function session($name = '', $default = null, $filter = '')
{ {
if (empty($this->session)) { if (empty($this->session)) {
$this->session = Container::get('session')->get(); $this->session = $this->app['session']->get();
} }
if (is_array($name)) { if (is_array($name)) {
@ -1053,7 +1072,7 @@ class Request
*/ */
public function cookie($name = '', $default = null, $filter = '') public function cookie($name = '', $default = null, $filter = '')
{ {
$cookie = Container::get('cookie'); $cookie = $this->app['cookie'];
if (empty($this->cookie)) { if (empty($this->cookie)) {
$this->cookie = $cookie->get(); $this->cookie = $cookie->get();
@ -1190,7 +1209,7 @@ class Request
public function env($name = '', $default = null, $filter = '') public function env($name = '', $default = null, $filter = '')
{ {
if (empty($this->env)) { if (empty($this->env)) {
$this->env = Container::get('env')->get(); $this->env = $this->app['env']->get();
} }
if (is_array($name)) { if (is_array($name)) {
@ -1514,7 +1533,7 @@ class Request
return true; return true;
} elseif (isset($server['HTTP_X_FORWARDED_PROTO']) && 'https' == $server['HTTP_X_FORWARDED_PROTO']) { } elseif (isset($server['HTTP_X_FORWARDED_PROTO']) && 'https' == $server['HTTP_X_FORWARDED_PROTO']) {
return true; return true;
} elseif ($this->config->get('https_agent_name') && isset($server[$this->config->get('https_agent_name')])) { } elseif ($this->config['https_agent_name'] && isset($server[$this->config['https_agent_name']])) {
return true; return true;
} }
@ -1536,7 +1555,7 @@ class Request
return $result; return $result;
} }
return $this->param($this->config->get('var_ajax')) ? true : $result; return $this->param($this->config['var_ajax']) ? true : $result;
} }
/** /**
@ -1553,7 +1572,7 @@ class Request
return $result; return $result;
} }
return $this->param($this->config->get('var_pjax')) ? true : $result; return $this->param($this->config['var_pjax']) ? true : $result;
} }
/** /**
@ -1572,7 +1591,7 @@ class Request
return $ip[$type]; return $ip[$type];
} }
$httpAgentIp = $this->config->get('http_agent_ip'); $httpAgentIp = $this->config['http_agent_ip'];
if ($httpAgentIp && isset($_SERVER[$httpAgentIp])) { if ($httpAgentIp && isset($_SERVER[$httpAgentIp])) {
$ip = $_SERVER[$httpAgentIp]; $ip = $_SERVER[$httpAgentIp];
@ -1866,7 +1885,7 @@ class Request
header($name . ': ' . $token); header($name . ': ' . $token);
} }
Container::get('session')->set($name, $token); $this->app['session']->set($name, $token);
return $token; return $token;
} }
@ -1934,7 +1953,7 @@ class Request
if (isset($fun)) { if (isset($fun)) {
$key = $fun($key); $key = $fun($key);
} }
$cache = Container::get('cache'); $cache = $this->app['cache'];
if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) { if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) {
// 读取缓存 // 读取缓存

View File

@ -21,6 +21,12 @@ class Response
*/ */
protected $data; protected $data;
/**
* 应用对象实例
* @var App
*/
protected $app;
/** /**
* 当前contentType * 当前contentType
* @var string * @var string
@ -82,6 +88,7 @@ class Response
$this->contentType($this->contentType, $this->charset); $this->contentType($this->contentType, $this->charset);
$this->code = $code; $this->code = $code;
$this->app = Container::get('app');
$this->header = array_merge($this->header, $header); $this->header = array_merge($this->header, $header);
} }
@ -115,24 +122,24 @@ class Response
public function send() public function send()
{ {
// 监听response_send // 监听response_send
Container::get('hook')->listen('response_send', $this); $this->app['hook']->listen('response_send', $this);
// 处理输出数据 // 处理输出数据
$data = $this->getContent(); $data = $this->getContent();
// Trace调试注入 // Trace调试注入
if ('cli' != PHP_SAPI && Container::get('env')->get('app_trace', Container::get('app')->config('app.app_trace'))) { if ('cli' != PHP_SAPI && $this->app['env']->get('app_trace', $this->app->config('app.app_trace'))) {
Container::get('debug')->inject($this, $data); $this->app['debug']->inject($this, $data);
} }
if (200 == $this->code && $this->allowCache) { if (200 == $this->code && $this->allowCache) {
$cache = Container::get('request')->getCache(); $cache = $this->app['request']->getCache();
if ($cache) { if ($cache) {
$this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate'; $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate';
$this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT'; $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT';
$this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT'; $this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT';
Container::get('cache')->tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]); $this->app['cache']->tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]);
} }
} }
@ -153,11 +160,11 @@ class Response
} }
// 监听response_end // 监听response_end
Container::get('hook')->listen('response_end', $this); $this->app['hook']->listen('response_end', $this);
// 清空当次请求有效的数据 // 清空当次请求有效的数据
if (!($this instanceof RedirectResponse)) { if (!($this instanceof RedirectResponse)) {
Container::get('session')->flush(); $this->app['session']->flush();
} }
} }

View File

@ -48,10 +48,10 @@ class Route
]; ];
/** /**
* 配置对象 * 应用对象
* @var Config * @var App
*/ */
protected $config; protected $app;
/** /**
* 请求对象 * 请求对象
@ -77,6 +77,12 @@ class Route
*/ */
protected $group; protected $group;
/**
* 配置参数
* @var array
*/
protected $config = [];
/** /**
* 路由绑定 * 路由绑定
* @var array * @var array
@ -119,14 +125,37 @@ class Route
*/ */
protected $autoSearchController = true; protected $autoSearchController = true;
public function __construct(Request $request) public function __construct(App $app, array $config = [])
{ {
$this->request = $request; $this->app = $app;
$this->request = $app['request'];
$this->config = $config;
$this->host = $this->request->host(true); $this->host = $this->request->host(true);
$this->setDefaultDomain(); $this->setDefaultDomain();
} }
public function config($name = null)
{
if (is_null($name)) {
return $this->config;
}
return isset($this->config[$name]) ? $this->config[$name] : null;
}
public static function __make(App $app, Config $config)
{
$config = $config->pull('app');
$route = new static($app, $config);
$route->lazy($config['url_lazy_route'])
->autoSearchController($config['controller_auto_search'])
->mergeRuleRegex($config['route_rule_merge']);
return $route;
}
/** /**
* 设置路由域名及分组(包括资源路由)是否延迟解析 * 设置路由域名及分组(包括资源路由)是否延迟解析
* @access public * @access public
@ -346,7 +375,7 @@ class Route
*/ */
public function getName($name = null) public function getName($name = null)
{ {
return Container::get('rule_name')->get($name); return $this->app['rule_name']->get($name);
} }
/** /**
@ -357,7 +386,7 @@ class Route
*/ */
public function setName($name) public function setName($name)
{ {
Container::get('rule_name')->import($name); $this->app['rule_name']->import($name);
return $this; return $this;
} }
@ -761,23 +790,23 @@ class Route
* 检测URL路由 * 检测URL路由
* @access public * @access public
* @param string $url URL地址 * @param string $url URL地址
* @param string $depr URL分隔符
* @param bool $must 是否强制路由 * @param bool $must 是否强制路由
* @param bool $completeMatch 路由是否完全匹配
* @return Dispatch * @return Dispatch
* @throws RouteNotFoundException * @throws RouteNotFoundException
*/ */
public function check($url, $depr = '/', $must = false, $completeMatch = false) public function check($url, $must = false)
{ {
// 自动检测域名路由 // 自动检测域名路由
$domain = $this->checkDomain(); $domain = $this->checkDomain();
$url = str_replace($depr, '|', $url); $url = str_replace($this->config['pathinfo_depr'], '|', $url);
$result = $domain->check($this->request, $url, $depr, $completeMatch); $completeMatch = $this->config['route_complete_match'];
$result = $domain->check($this->request, $url, $completeMatch);
if (false === $result && !empty($this->cross)) { if (false === $result && !empty($this->cross)) {
// 检测跨域路由 // 检测跨域路由
$result = $this->cross->check($this->request, $url, $depr, $completeMatch); $result = $this->cross->check($this->request, $url, $completeMatch);
} }
if (false !== $result) { if (false !== $result) {
@ -789,7 +818,9 @@ class Route
} }
// 默认路由解析 // 默认路由解析
return new UrlDispatch($url, ['depr' => $depr, 'auto_search' => $this->autoSearchController]); $ruleItem = new RuleItem($this, $this->group, '', '', $url);
return new UrlDispatch($this->request, $ruleItem, $url, ['auto_search' => $this->autoSearchController]);
} }
/** /**

View File

@ -15,6 +15,12 @@ use think\exception\ClassNotFoundException;
class Session class Session
{ {
/**
* 配置参数
* @var array
*/
protected $config = [];
/** /**
* 前缀 * 前缀
* @var string * @var string
@ -51,6 +57,11 @@ class Session
*/ */
protected $lock = false; protected $lock = false;
public function __construct(array $config = [])
{
$this->config = $config;
}
/** /**
* 设置或者获取session作用域前缀 * 设置或者获取session作用域前缀
* @access public * @access public
@ -68,6 +79,22 @@ class Session
} }
} }
public static function __make(Config $config)
{
return new static($config->pull('session'));
}
/**
* 配置
* @access public
* @param array $config
* @return void
*/
public function setConfig(array $config = [])
{
$this->config = array_merge($this->config, array_change_key_case($config));
}
/** /**
* session初始化 * session初始化
* @access public * @access public
@ -77,12 +104,8 @@ class Session
*/ */
public function init(array $config = []) public function init(array $config = [])
{ {
if (empty($config)) { $config = $config ?: $this->config;
$config = Container::get('config')->pull('session');
}
// 记录初始化信息
Container::get('app')->log('[ SESSION ] INIT ' . var_export($config, true));
$isDoStart = false; $isDoStart = false;
if (isset($config['use_trans_sid'])) { if (isset($config['use_trans_sid'])) {
ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0); ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0);
@ -161,6 +184,8 @@ class Session
} else { } else {
$this->init = false; $this->init = false;
} }
return $this;
} }
/** /**
@ -253,8 +278,7 @@ class Session
*/ */
protected function initDriver() protected function initDriver()
{ {
// 不在 init 方法中实例化lockDriver是因为 init 方法不一定先于 set 或 get 方法调用 $config = $this->config;
$config = Container::get('config')->pull('session');
if (!empty($config['type']) && isset($config['use_lock']) && $config['use_lock']) { if (!empty($config['type']) && isset($config['use_lock']) && $config['use_lock']) {
// 读取session驱动 // 读取session驱动

View File

@ -20,6 +20,7 @@ use think\exception\TemplateNotFoundException;
*/ */
class Template class Template
{ {
protected $app;
/** /**
* 模板变量 * 模板变量
* @var array * @var array
@ -83,9 +84,10 @@ class Template
* @access public * @access public
* @param array $config * @param array $config
*/ */
public function __construct(array $config = []) public function __construct(App $app, array $config = [])
{ {
$this->config['cache_path'] = Container::get('app')->getRuntimePath() . 'temp/'; $this->app = $app;
$this->config['cache_path'] = $app->getRuntimePath() . 'temp/';
$this->config = array_merge($this->config, $config); $this->config = array_merge($this->config, $config);
$this->config['taglib_begin_origin'] = $this->config['taglib_begin']; $this->config['taglib_begin_origin'] = $this->config['taglib_begin'];
@ -97,10 +99,14 @@ class Template
$this->config['tpl_end'] = preg_quote($this->config['tpl_end'], '/'); $this->config['tpl_end'] = preg_quote($this->config['tpl_end'], '/');
// 初始化模板编译存储器 // 初始化模板编译存储器
$type = $this->config['compile_type'] ? $this->config['compile_type'] : 'File'; $type = $this->config['compile_type'] ? $this->config['compile_type'] : 'File';
$class = false !== strpos($type, '\\') ? $type : '\\think\\template\\driver\\' . ucwords($type);
$this->storage = new $class(); $this->storage = Loader::factory($type, '\\think\\template\\driver\\', null);
}
public static function __make(Config $config)
{
return new static($config->pull('template'));
} }
/** /**
@ -189,7 +195,7 @@ class Template
$this->config($config); $this->config($config);
} }
$cache = Container::get('cache'); $cache = $this->app['cache'];
if (!empty($this->config['cache_id']) && $this->config['display_cache']) { if (!empty($this->config['cache_id']) && $this->config['display_cache']) {
// 读取渲染缓存 // 读取渲染缓存
@ -337,7 +343,7 @@ class Template
{ {
if ($cacheId && $this->config['display_cache']) { if ($cacheId && $this->config['display_cache']) {
// 缓存页面输出 // 缓存页面输出
return Container::get('cache')->has($cacheId); return $this->app['cache']->has($cacheId);
} }
return false; return false;
@ -1218,10 +1224,10 @@ class Template
} }
if ($this->config['view_base']) { if ($this->config['view_base']) {
$module = isset($module) ? $module : Container::get('request')->module(); $module = isset($module) ? $module : $this->app['request']->module();
$path = $this->config['view_base'] . ($module ? $module . DIRECTORY_SEPARATOR : ''); $path = $this->config['view_base'] . ($module ? $module . DIRECTORY_SEPARATOR : '');
} else { } else {
$path = isset($module) ? Container::get('app')->getAppPath() . $module . DIRECTORY_SEPARATOR . basename($this->config['view_path']) . DIRECTORY_SEPARATOR : $this->config['view_path']; $path = isset($module) ? $this->app->getAppPath() . $module . DIRECTORY_SEPARATOR . basename($this->config['view_path']) . DIRECTORY_SEPARATOR : $this->config['view_path'];
} }
$template = $path . $template . '.' . ltrim($this->config['view_suffix'], '.'); $template = $path . $template . '.' . ltrim($this->config['view_suffix'], '.');

View File

@ -13,6 +13,12 @@ namespace think;
class Url class Url
{ {
/**
* 配置参数
* @var array
*/
protected $config = [];
/** /**
* ROOT地址 * ROOT地址
* @var string * @var string
@ -31,9 +37,10 @@ class Url
*/ */
protected $app; protected $app;
public function __construct(App $app) public function __construct(App $app, array $config = [])
{ {
$this->app = $app; $this->app = $app;
$this->config = $config;
if (is_file($app->getRuntimePath() . 'route.php')) { if (is_file($app->getRuntimePath() . 'route.php')) {
// 读取路由映射文件 // 读取路由映射文件
@ -41,6 +48,22 @@ class Url
} }
} }
/**
* 初始化
* @access public
* @param array $config
* @return void
*/
public function init(array $config = [])
{
$this->config = array_merge($this->config, array_change_key_case($config));
}
public static function __make(App $app, Config $config)
{
return new static($app, $config->pull('app'));
}
/** /**
* URL生成 支持路由反射 * URL生成 支持路由反射
* @access public * @access public
@ -105,7 +128,7 @@ class Url
$url = $match[0]; $url = $match[0];
if (!empty($match[1])) { if (!empty($match[1])) {
$host = $this->app['config']->get('app_host') ?: $this->app['request']->host(true); $host = $this->config['app_host'] ?: $this->app['request']->host(true);
if ($domain || $match[1] != $host) { if ($domain || $match[1] != $host) {
$domain = $match[1]; $domain = $match[1];
} }
@ -166,7 +189,7 @@ class Url
} }
// 还原URL分隔符 // 还原URL分隔符
$depr = $this->app['config']->get('pathinfo_depr'); $depr = $this->config['pathinfo_depr'];
$url = str_replace('/', $depr, $url); $url = str_replace('/', $depr, $url);
// URL后缀 // URL后缀
@ -182,11 +205,11 @@ class Url
// 参数组装 // 参数组装
if (!empty($vars)) { if (!empty($vars)) {
// 添加参数 // 添加参数
if ($this->app['config']->get('url_common_param')) { if ($this->config['url_common_param']) {
$vars = http_build_query($vars); $vars = http_build_query($vars);
$url .= $suffix . '?' . $vars . $anchor; $url .= $suffix . '?' . $vars . $anchor;
} else { } else {
$paramType = $this->app['config']->get('url_param_type'); $paramType = $this->config['url_param_type'];
foreach ($vars as $var => $val) { foreach ($vars as $var => $val) {
if ('' !== trim($val)) { if ('' !== trim($val)) {
@ -244,7 +267,7 @@ class Url
$module = empty($path) ? $module : array_pop($path) . '/'; $module = empty($path) ? $module : array_pop($path) . '/';
} }
if ($this->app['config']->get('url_convert')) { if ($this->config['url_convert']) {
$action = strtolower($action); $action = strtolower($action);
$controller = Loader::parseName($controller); $controller = Loader::parseName($controller);
} }
@ -265,7 +288,7 @@ class Url
$rootDomain = $this->app['request']->rootDomain(); $rootDomain = $this->app['request']->rootDomain();
if (true === $domain) { if (true === $domain) {
// 自动判断域名 // 自动判断域名
$domain = $this->app['config']->get('app_host') ?: $this->app['request']->host(true); $domain = $this->config['app_host'] ?: $this->app['request']->host(true);
$domains = $this->app['route']->getDomains(); $domains = $this->app['route']->getDomains();
@ -302,7 +325,7 @@ class Url
if (false !== strpos($domain, '://')) { if (false !== strpos($domain, '://')) {
$scheme = ''; $scheme = '';
} else { } else {
$scheme = $this->app['request']->isSsl() || $this->app['config']->get('is_https') ? 'https://' : 'http://'; $scheme = $this->app['request']->isSsl() || $this->config['is_https'] ? 'https://' : 'http://';
} }
@ -313,7 +336,7 @@ class Url
protected function parseSuffix($suffix) protected function parseSuffix($suffix)
{ {
if ($suffix) { if ($suffix) {
$suffix = true === $suffix ? $this->app['config']->get('url_html_suffix') : $suffix; $suffix = true === $suffix ? $this->config['url_html_suffix'] : $suffix;
if ($pos = strpos($suffix, '|')) { if ($pos = strpos($suffix, '|')) {
$suffix = substr($suffix, 0, $pos); $suffix = substr($suffix, 0, $pos);
@ -332,7 +355,7 @@ class Url
return [rtrim($url, '?/-'), $domain, $suffix]; return [rtrim($url, '?/-'), $domain, $suffix];
} }
$type = $this->app['config']->get('url_common_param'); $type = $this->config['url_common_param'];
foreach ($pattern as $key => $val) { foreach ($pattern as $key => $val) {
if (isset($vars[$key])) { if (isset($vars[$key])) {

View File

@ -1078,7 +1078,7 @@ class Validate
*/ */
public function requireCallback($value, $rule, $data) public function requireCallback($value, $rule, $data)
{ {
$result = call_user_func_array($rule, [$value, $data]); $result = call_user_func_array([$this, $rule], [$value, $data]);
if ($result) { if ($result) {
return !empty($value) || '0' == $value; return !empty($value) || '0' == $value;
@ -1447,12 +1447,12 @@ class Validate
$scene = $this->currentScene; $scene = $this->currentScene;
} }
$this->only = $this->append = $this->remove = [];
if (empty($scene)) { if (empty($scene)) {
return; return;
} }
$this->only = $this->append = $this->remove = [];
if (method_exists($this, 'scene' . $scene)) { if (method_exists($this, 'scene' . $scene)) {
call_user_func([$this, 'scene' . $scene]); call_user_func([$this, 'scene' . $scene]);
} elseif (isset($this->scene[$scene])) { } elseif (isset($this->scene[$scene])) {

View File

@ -51,6 +51,11 @@ class View
return $this; return $this;
} }
public static function __make(Config $config)
{
return (new static())->init($config->pull('template'));
}
/** /**
* 模板变量静态赋值 * 模板变量静态赋值
* @access public * @access public
@ -102,13 +107,11 @@ class View
$type = !empty($options['type']) ? $options['type'] : 'Think'; $type = !empty($options['type']) ? $options['type'] : 'Think';
} }
$class = false !== strpos($type, '\\') ? $type : '\\think\\view\\driver\\' . ucfirst($type);
if (isset($options['type'])) { if (isset($options['type'])) {
unset($options['type']); unset($options['type']);
} }
$this->engine = new $class($options); $this->engine = Loader::factory($type, '\\think\\view\\driver\\', $options);
return $this; return $this;
} }

View File

@ -13,12 +13,19 @@ namespace think\config\driver;
class Ini class Ini
{ {
public function parse($config) protected $config;
public function __construct($config)
{ {
if (is_file($config)) { $this->config = $config;
return parse_ini_file($config, true); }
public function parse()
{
if (is_file($this->config)) {
return parse_ini_file($this->config, true);
} else { } else {
return parse_ini_string($config, true); return parse_ini_string($this->config, true);
} }
} }
} }

View File

@ -13,14 +13,19 @@ namespace think\config\driver;
class Json class Json
{ {
public function parse($config) protected $config;
public function __construct($config)
{ {
if (is_file($config)) { if (is_file($config)) {
$config = file_get_contents($config); $config = file_get_contents($config);
} }
$result = json_decode($config, true); $this->config = $config;
}
return $result; public function parse()
{
return json_decode($this->config, true);
} }
} }

View File

@ -13,12 +13,19 @@ namespace think\config\driver;
class Xml class Xml
{ {
public function parse($config) protected $config;
public function __construct($config)
{ {
if (is_file($config)) { $this->config = $config;
$content = simplexml_load_file($config); }
public function parse()
{
if (is_file($this->config)) {
$content = simplexml_load_file($this->config);
} else { } else {
$content = simplexml_load_string($config); $content = simplexml_load_string($this->config);
} }
$result = (array) $content; $result = (array) $content;

View File

@ -15,6 +15,7 @@ use think\console\Input;
use think\console\input\Option; use think\console\input\Option;
use think\console\Output; use think\console\Output;
use think\facade\App; use think\facade\App;
use think\facade\Cache;
class Clear extends Command class Clear extends Command
{ {
@ -25,6 +26,7 @@ class Clear extends Command
->setName('clear') ->setName('clear')
->addOption('path', 'd', Option::VALUE_OPTIONAL, 'path to clear', null) ->addOption('path', 'd', Option::VALUE_OPTIONAL, 'path to clear', null)
->addOption('cache', 'c', Option::VALUE_NONE, 'clear cache file') ->addOption('cache', 'c', Option::VALUE_NONE, 'clear cache file')
->addOption('route', 'u', Option::VALUE_NONE, 'clear route cache')
->addOption('log', 'l', Option::VALUE_NONE, 'clear log file') ->addOption('log', 'l', Option::VALUE_NONE, 'clear log file')
->addOption('dir', 'r', Option::VALUE_NONE, 'clear empty dir') ->addOption('dir', 'r', Option::VALUE_NONE, 'clear empty dir')
->setDescription('Clear runtime file'); ->setDescription('Clear runtime file');
@ -32,16 +34,21 @@ class Clear extends Command
protected function execute(Input $input, Output $output) protected function execute(Input $input, Output $output)
{ {
if ($input->getOption('cache')) { if ($input->getOption('route')) {
$path = App::getRuntimePath() . 'cache'; Cache::clear('route_cache');
} elseif ($input->getOption('log')) {
$path = App::getRuntimePath() . 'log';
} else { } else {
$path = $input->getOption('path') ?: App::getRuntimePath(); if ($input->getOption('cache')) {
$path = App::getRuntimePath() . 'cache';
} elseif ($input->getOption('log')) {
$path = App::getRuntimePath() . 'log';
} else {
$path = $input->getOption('path') ?: App::getRuntimePath();
}
$rmdir = $input->getOption('dir') ? true : false;
$this->clear(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, $rmdir);
} }
$rmdir = $input->getOption('dir') ? true : false;
$this->clear(rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR, $rmdir);
$output->writeln("<info>Clear Successed</info>"); $output->writeln("<info>Clear Successed</info>");
} }

View File

@ -20,6 +20,7 @@ use think\db\exception\BindParamException;
use think\Debug; use think\Debug;
use think\Exception; use think\Exception;
use think\exception\PDOException; use think\exception\PDOException;
use think\Loader;
abstract class Connection abstract class Connection
{ {
@ -182,22 +183,18 @@ abstract class Connection
} }
if (true === $name || !isset(self::$instance[$name])) { if (true === $name || !isset(self::$instance[$name])) {
// 解析连接参数 支持数组和字符串 if (empty($config['type'])) {
$options = self::parseConfig($config);
if (empty($options['type'])) {
throw new InvalidArgumentException('Undefined db type'); throw new InvalidArgumentException('Undefined db type');
} }
$class = false !== strpos($options['type'], '\\') ? $options['type'] : '\\think\\db\\connector\\' . ucwords($options['type']);
// 记录初始化信息 // 记录初始化信息
Container::get('app')->log('[ DB ] INIT ' . $options['type']); Container::get('app')->log('[ DB ] INIT ' . $config['type']);
if (true === $name) { if (true === $name) {
$name = md5(serialize($config)); $name = md5(serialize($config));
} }
self::$instance[$name] = new $class($options); self::$instance[$name] = Loader::factory($config['type'], '\\think\\db\\connector\\', $config);
} }
return self::$instance[$name]; return self::$instance[$name];
@ -2149,60 +2146,4 @@ abstract class Connection
} }
} }
/**
* 数据库连接参数解析
* @access private
* @param mixed $config
* @return array
*/
private static function parseConfig($config)
{
if (empty($config)) {
$config = Container::get('config')->pull('database');
} elseif (is_string($config) && false === strpos($config, '/')) {
// 支持读取配置参数
$config = Container::get('config')->get('database.' . $config);
}
if (is_string($config)) {
return self::parseDsnConfig($config);
} else {
return $config;
}
}
/**
* DSN解析
* 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1&param2=val2#utf8
* @access private
* @param string $dsnStr
* @return array
*/
private static function parseDsnConfig($dsnStr)
{
$info = parse_url($dsnStr);
if (!$info) {
return [];
}
$dsn = [
'type' => $info['scheme'],
'username' => isset($info['user']) ? $info['user'] : '',
'password' => isset($info['pass']) ? $info['pass'] : '',
'hostname' => isset($info['host']) ? $info['host'] : '',
'hostport' => isset($info['port']) ? $info['port'] : '',
'database' => !empty($info['path']) ? ltrim($info['path'], '/') : '',
'charset' => isset($info['fragment']) ? $info['fragment'] : 'utf8',
];
if (isset($info['query'])) {
parse_str($info['query'], $dsn['params']);
} else {
$dsn['params'] = [];
}
return $dsn;
}
} }

View File

@ -14,6 +14,7 @@ namespace think\db;
use PDO; use PDO;
use think\Collection; use think\Collection;
use think\Container; use think\Container;
use think\Db;
use think\db\exception\BindParamException; use think\db\exception\BindParamException;
use think\db\exception\DataNotFoundException; use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException; use think\db\exception\ModelNotFoundException;
@ -28,12 +29,6 @@ use think\Paginator;
class Query class Query
{ {
/**
* 数据库连接对象列表
* @var array
*/
protected static $connections = [];
/** /**
* 当前数据库连接对象 * 当前数据库连接对象
* @var Connection * @var Connection
@ -122,7 +117,7 @@ class Query
public function __construct(Connection $connection = null) public function __construct(Connection $connection = null)
{ {
if (is_null($connection)) { if (is_null($connection)) {
$this->connection = Connection::instance(); $this->connection = Db::connect();
} else { } else {
$this->connection = $connection; $this->connection = $connection;
} }
@ -302,29 +297,6 @@ class Query
return $this->prefix . Loader::parseName($name); return $this->prefix . Loader::parseName($name);
} }
/**
* 切换数据库连接
* @access public
* @param mixed $config 连接配置
* @param bool|string $name 连接标识 true 强制重新连接
* @return $this|object
* @throws Exception
*/
public function connect($config = [], $name = false)
{
$this->connection = Connection::instance($config, $name);
$query = $this->connection->getConfig('query');
if (__CLASS__ != trim($query, '\\')) {
return new $query($this->connection);
}
$this->prefix = $this->connection->getConfig('prefix');
return $this;
}
/** /**
* 执行查询 返回数据集 * 执行查询 返回数据集
* @access public * @access public
@ -653,7 +625,7 @@ class Query
if (!empty($this->options['fetch_sql'])) { if (!empty($this->options['fetch_sql'])) {
return $result; return $result;
} elseif ($force) { } elseif ($force) {
$result += 0; $result = (float) $result;
} }
return $result; return $result;

View File

@ -39,9 +39,9 @@ use think\Facade;
* @method \think\Route alias(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册别名路由 * @method \think\Route alias(string $rule, mixed $route, array $option = [], array $pattern = []) static 注册别名路由
* @method \think\Route setMethodPrefix(mixed $method, string $prefix = '') static 设置不同请求类型下面的方法前缀 * @method \think\Route setMethodPrefix(mixed $method, string $prefix = '') static 设置不同请求类型下面的方法前缀
* @method \think\Route rest(string $name, array $resource = []) static rest方法定义和修改 * @method \think\Route rest(string $name, array $resource = []) static rest方法定义和修改
* @method \think\RuleItem miss(string $route, string $method = '*', array $option = []) static 注册未匹配路由规则后的处理 * @method \think\Route\RuleItem miss(string $route, string $method = '*', array $option = []) static 注册未匹配路由规则后的处理
* @method \think\RuleItem auto(string $route) static 注册一个自动解析的URL路由 * @method \think\Route\RuleItem auto(string $route) static 注册一个自动解析的URL路由
* @method \think\Dispatch check(string $url, string $depr = '/', bool $must = false, bool $completeMatch = false) static 检测URL路由 * @method \think\Route\Dispatch check(string $url, string $depr = '/', bool $must = false, bool $completeMatch = false) static 检测URL路由
*/ */
class Route extends Facade class Route extends Facade
{ {

View File

@ -19,7 +19,7 @@ use think\Facade;
* @method void init(array $config = []) static session初始化 * @method void init(array $config = []) static session初始化
* @method bool has(string $name,string $prefix = null) static 判断session数据 * @method bool has(string $name,string $prefix = null) static 判断session数据
* @method mixed prefix(string $prefix = '') static 设置或者获取session作用域前缀 * @method mixed prefix(string $prefix = '') static 设置或者获取session作用域前缀
* @method mixed get(string $name,string $prefix = null) static session获取 * @method mixed get(string $name = '',string $prefix = null) static session获取
* @method mixed pull(string $name,string $prefix = null) static session获取并删除 * @method mixed pull(string $name,string $prefix = null) static session获取并删除
* @method void push(string $key, mixed $value) static 添加数据到一个session数组 * @method void push(string $key, mixed $value) static 添加数据到一个session数组
* @method void set(string $name, mixed $value , string $prefix = null) static 设置session数据 * @method void set(string $name, mixed $value , string $prefix = null) static 设置session数据

View File

@ -448,7 +448,7 @@ trait Attribute
} elseif (isset($this->type[$name])) { } elseif (isset($this->type[$name])) {
// 类型转换 // 类型转换
$value = $this->readTransform($value, $this->type[$name]); $value = $this->readTransform($value, $this->type[$name]);
} elseif (in_array($name, [$this->createTime, $this->updateTime])) { } elseif ($this->autoWriteTimestamp && in_array($name, [$this->createTime, $this->updateTime])) {
if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [ if (is_string($this->autoWriteTimestamp) && in_array(strtolower($this->autoWriteTimestamp), [
'datetime', 'datetime',
'date', 'date',

View File

@ -11,7 +11,6 @@
namespace think\response; namespace think\response;
use think\Container;
use think\Response; use think\Response;
class Jsonp extends Response class Jsonp extends Response
@ -36,7 +35,7 @@ class Jsonp extends Response
{ {
try { try {
// 返回JSON数据格式到客户端 包含状态信息 [当url_common_param为false时是无法获取到$_GET的数据的故使用Request来获取<xiaobo.sun@qq.com>] // 返回JSON数据格式到客户端 包含状态信息 [当url_common_param为false时是无法获取到$_GET的数据的故使用Request来获取<xiaobo.sun@qq.com>]
$var_jsonp_handler = Container::get('request')->param($this->options['var_jsonp_handler'], ""); $var_jsonp_handler = $this->app['request']->param($this->options['var_jsonp_handler'], "");
$handler = !empty($var_jsonp_handler) ? $var_jsonp_handler : $this->options['default_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']);

View File

@ -11,7 +11,6 @@
namespace think\response; namespace think\response;
use think\Container;
use think\Response; use think\Response;
class Jump extends Response class Jump extends Response
@ -27,10 +26,7 @@ class Jump extends Response
*/ */
protected function output($data) protected function output($data)
{ {
$config = Container::get('config'); $data = $this->app['view']->fetch($this->options['jump_template'], $data);
$data = Container::get('view')
->init($config->pull('template'))
->fetch($this->options['jump_template'], $data);
return $data; return $data;
} }
} }

View File

@ -11,7 +11,6 @@
namespace think\response; namespace think\response;
use think\Container;
use think\Response; use think\Response;
class Redirect extends Response class Redirect extends Response
@ -51,7 +50,7 @@ class Redirect extends Response
*/ */
public function with($name, $value = null) public function with($name, $value = null)
{ {
$session = Container::get('session'); $session = $this->app['session'];
if (is_array($name)) { if (is_array($name)) {
foreach ($name as $key => $val) { foreach ($name as $key => $val) {
@ -74,7 +73,7 @@ class Redirect extends Response
if (strpos($this->data, '://') || (0 === strpos($this->data, '/') && empty($this->params))) { if (strpos($this->data, '://') || (0 === strpos($this->data, '/') && empty($this->params))) {
return $this->data; return $this->data;
} else { } else {
return Container::get('url')->build($this->data, $this->params); return $this->app['url']->build($this->data, $this->params);
} }
} }
@ -92,7 +91,7 @@ class Redirect extends Response
*/ */
public function remember() public function remember()
{ {
Container::get('session')->set('redirect_url', Container::get('request')->url()); $this->app['session']->set('redirect_url', $this->app['request']->url());
return $this; return $this;
} }
@ -104,7 +103,7 @@ class Redirect extends Response
*/ */
public function restore() public function restore()
{ {
$session = Container::get('session'); $session = $this->app['session'];
if ($session->has('redirect_url')) { if ($session->has('redirect_url')) {
$this->data = $session->get('redirect_url'); $this->data = $session->get('redirect_url');

View File

@ -11,7 +11,6 @@
namespace think\response; namespace think\response;
use think\Container;
use think\Response; use think\Response;
class View extends Response class View extends Response
@ -31,9 +30,7 @@ class View extends Response
protected function output($data) protected function output($data)
{ {
// 渲染模板输出 // 渲染模板输出
$config = Container::get('config'); return $this->app['view']
return Container::get('view')
->init($config->pull('template'))
->filter($this->filter) ->filter($this->filter)
->fetch($data, $this->vars); ->fetch($data, $this->vars);
} }
@ -91,9 +88,7 @@ class View extends Response
*/ */
public function exists($name) public function exists($name)
{ {
return Container::get('view') return $this->app['view']->exists($name);
->init(Container::get('config')->pull('template'))
->exists($name);
} }
} }

View File

@ -40,11 +40,10 @@ class AliasRule extends Domain
* @access public * @access public
* @param Request $request 请求对象 * @param Request $request 请求对象
* @param string $url 访问地址 * @param string $url 访问地址
* @param string $depr 路径分隔符
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return Dispatch|false * @return Dispatch|false
*/ */
public function check($request, $url, $depr = '/', $completeMatch = false) public function check($request, $url, $completeMatch = false)
{ {
if ($dispatch = $this->checkCrossDomain($request)) { if ($dispatch = $this->checkCrossDomain($request)) {
// 允许跨域 // 允许跨域
@ -82,13 +81,13 @@ class AliasRule extends Domain
if (0 === strpos($this->route, '\\')) { if (0 === strpos($this->route, '\\')) {
// 路由到类 // 路由到类
return $this->bindToClass($bind, substr($this->route, 1)); return $this->bindToClass($request, $bind, substr($this->route, 1));
} elseif (0 === strpos($this->route, '@')) { } elseif (0 === strpos($this->route, '@')) {
// 路由到控制器类 // 路由到控制器类
return $this->bindToController($bind, substr($this->route, 1)); return $this->bindToController($request, $bind, substr($this->route, 1));
} else { } else {
// 路由到模块/控制器 // 路由到模块/控制器
return $this->bindToModule($bind, $this->route); return $this->bindToModule($request, $bind, $this->route);
} }
} }

View File

@ -12,32 +12,291 @@
namespace think\route; namespace think\route;
use think\Container; use think\Container;
use think\exception\ValidateException;
use think\Request;
use think\Response;
use think\route\dispatch\ResponseDispatch;
abstract class Dispatch abstract class Dispatch
{ {
// 应用实例 /**
* 应用对象
* @var App
*/
protected $app; protected $app;
// 调度信息
/**
* 请求对象
* @var Request
*/
protected $request;
/**
* 路由规则
* @var RuleItem
*/
protected $router;
/**
* 调度信息
* @var mixed
*/
protected $dispatch; protected $dispatch;
// 调度参数
/**
* 调度参数
* @var array
*/
protected $param; protected $param;
// 状态码
/**
* 状态码
* @var string
*/
protected $code; protected $code;
// 是否进行大小写转换
/**
* 是否进行大小写转换
* @var bool
*/
protected $convert; protected $convert;
public function __construct($dispatch, $param = [], $code = null) public function __construct(Request $request, RuleItem $router, $dispatch, $param = [], $code = null)
{ {
$this->request = $request;
$this->router = $router;
$this->app = Container::get('app'); $this->app = Container::get('app');
$this->dispatch = $dispatch; $this->dispatch = $dispatch;
$this->param = $param; $this->param = $param;
$this->code = $code; $this->code = $code;
if (isset($param['convert'])) {
$this->convert = $param['convert'];
}
// 设置请求的路由信息
$this->request->routeInfo([
'rule' => $this->router->getRule(),
'route' => $this->router->getRoute(),
'option' => $this->router->getOption(),
'var' => $this->router->getVars(),
]);
// 执行路由后置操作
$this->routeAfter();
// 初始化
$this->init(); $this->init();
} }
protected function init() protected function init()
{} {}
/**
* 检查路由后置操作
* @access protected
* @return void
*/
protected function routeAfter()
{
// 记录匹配的路由信息
$option = $this->router->getOption();
$matches = $this->router->getVars();
// 添加中间件
if (!empty($option['middleware'])) {
$this->app['middleware']->import($option['middleware']);
}
// 绑定模型数据
if (!empty($option['model'])) {
$this->createBindModel($option['model'], $matches);
}
// 指定Header数据
if (!empty($option['header'])) {
$header = $option['header'];
$this->app['hook']->add('response_send', function ($response) use ($header) {
$response->header($header);
});
}
// 指定Response响应数据
if (!empty($option['response'])) {
$this->app['hook']->add('response_send', $option['response']);
}
// 开启请求缓存
if (isset($option['cache']) && $this->request->isGet()) {
$this->parseRequestCache($option['cache']);
}
if (!empty($option['append'])) {
$this->request->route($option['append']);
}
}
/**
* 执行路由调度
* @access public
* @return mixed
*/
public function run()
{
$option = $this->router->getOption();
// 检测路由after行为
if (!empty($option['after'])) {
$dispatch = $this->checkAfter($option['after']);
if ($dispatch instanceof Response) {
return $dispatch;
}
}
// 数据自动验证
if (isset($option['validate'])) {
$this->autoValidate($option['validate'], $request);
}
return $this->exec();
}
/**
* 检查路由后置行为
* @access protected
* @param mixed $after 后置行为
* @return mixed
*/
protected function checkAfter($after)
{
$this->app['log']->notice('路由后置行为建议使用中间件替代!');
$hook = $this->app['hook'];
$result = null;
foreach ((array) $after as $behavior) {
$result = $hook->exec($behavior);
if (!is_null($result)) {
break;
}
}
// 路由规则重定向
if ($result instanceof Response) {
return new ResponseDispatch($result, $this->router);
}
return false;
}
/**
* 验证数据
* @access protected
* @param array $option
* @param \think\Request $request
* @return void
* @throws ValidateException
*/
protected function autoValidate($option, $request)
{
list($validate, $scene, $message, $batch) = $option;
if (is_array($validate)) {
// 指定验证规则
$v = $this->app->validate();
$v->rule($validate);
} else {
// 调用验证器
$v = $this->app->validate($validate);
if (!empty($scene)) {
$v->scene($scene);
}
}
if (!empty($message)) {
$v->message($message);
}
// 批量验证
if ($batch) {
$v->batch(true);
}
if (!$v->check($request->param())) {
throw new ValidateException($v->getError());
}
}
/**
* 处理路由请求缓存
* @access protected
* @param Request $request 请求对象
* @param string|array $cache 路由缓存
* @return void
*/
protected function parseRequestCache($cache)
{
if (is_array($cache)) {
list($key, $expire, $tag) = array_pad($cache, 3, null);
} else {
$key = str_replace('|', '/', $this->request->url());
$expire = $cache;
$tag = null;
}
$this->request->cache($key, $expire, $tag);
}
/**
* 路由绑定模型实例
* @access protected
* @param array|\Clousre $bindModel 绑定模型
* @param array $matches 路由变量
* @return void
*/
protected function createBindModel($bindModel, $matches)
{
foreach ($bindModel as $key => $val) {
if ($val instanceof \Closure) {
$result = $this->app->invokeFunction($val, $matches);
} else {
$fields = explode('&', $key);
if (is_array($val)) {
list($model, $exception) = $val;
} else {
$model = $val;
$exception = true;
}
$where = [];
$match = true;
foreach ($fields as $field) {
if (!isset($matches[$field])) {
$match = false;
break;
} else {
$where[] = [$field, '=', $matches[$field]];
}
}
if ($match) {
$query = strpos($model, '\\') ? $model::where($where) : $this->app->model($model)->where($where);
$result = $query->failException($exception)->find();
}
}
if (!empty($result)) {
// 注入容器
$this->app->instance(get_class($result), $result);
}
}
}
public function convert($convert) public function convert($convert)
{ {
$this->convert = $convert; $this->convert = $convert;
@ -55,6 +314,6 @@ abstract class Dispatch
return $this->param; return $this->param;
} }
abstract public function run(); abstract public function exec();
} }

View File

@ -45,21 +45,20 @@ class Domain extends RuleGroup
* @access public * @access public
* @param Request $request 请求对象 * @param Request $request 请求对象
* @param string $url 访问地址 * @param string $url 访问地址
* @param string $depr 路径分隔符
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return Dispatch|false * @return Dispatch|false
*/ */
public function check($request, $url, $depr = '/', $completeMatch = false) public function check($request, $url, $completeMatch = false)
{ {
// 检测别名路由 // 检测别名路由
$result = $this->checkRouteAlias($request, $url, $depr); $result = $this->checkRouteAlias($request, $url);
if (false !== $result) { if (false !== $result) {
return $result; return $result;
} }
// 检测URL绑定 // 检测URL绑定
$result = $this->checkUrlBind($url, $depr); $result = $this->checkUrlBind($request, $url);
if (!empty($this->option['append'])) { if (!empty($this->option['append'])) {
$request->route($this->option['append']); $request->route($this->option['append']);
@ -76,7 +75,7 @@ class Domain extends RuleGroup
unset($this->option['middleware']); unset($this->option['middleware']);
} }
return parent::check($request, $url, $depr, $completeMatch); return parent::check($request, $url, $completeMatch);
} }
/** /**
@ -98,26 +97,25 @@ class Domain extends RuleGroup
* @access private * @access private
* @param Request $request * @param Request $request
* @param string $url URL地址 * @param string $url URL地址
* @param string $depr URL分隔符
* @return Dispatch|false * @return Dispatch|false
*/ */
private function checkRouteAlias($request, $url, $depr) private function checkRouteAlias($request, $url)
{ {
$alias = strpos($url, '|') ? strstr($url, '|', true) : $url; $alias = strpos($url, '|') ? strstr($url, '|', true) : $url;
$item = $this->router->getAlias($alias); $item = $this->router->getAlias($alias);
return $item ? $item->check($request, $url, $depr) : false; return $item ? $item->check($request, $url) : false;
} }
/** /**
* 检测URL绑定 * 检测URL绑定
* @access private * @access private
* @param Request $request
* @param string $url URL地址 * @param string $url URL地址
* @param string $depr URL分隔符
* @return Dispatch|false * @return Dispatch|false
*/ */
private function checkUrlBind($url, $depr = '/') private function checkUrlBind($request, $url)
{ {
if (!empty($this->bind)) { if (!empty($this->bind)) {
$bind = $this->bind; $bind = $this->bind;
@ -137,7 +135,7 @@ class Domain extends RuleGroup
]; ];
if (isset($bindTo[$type])) { if (isset($bindTo[$type])) {
return $this->{$bindTo[$type]}($url, $bind, $depr); return $this->{$bindTo[$type]}($request, $url, $bind);
} }
} }
@ -156,78 +154,82 @@ class Domain extends RuleGroup
/** /**
* 绑定到类 * 绑定到类
* @access protected * @access protected
* @param Request $request
* @param string $url URL地址 * @param string $url URL地址
* @param string $class 类名(带命名空间) * @param string $class 类名(带命名空间)
* @return CallbackDispatch * @return CallbackDispatch
*/ */
protected function bindToClass($url, $class) protected function bindToClass($request, $url, $class)
{ {
$array = explode('|', $url, 2); $array = explode('|', $url, 2);
$action = !empty($array[0]) ? $array[0] : Container::get('config')->get('default_action'); $action = !empty($array[0]) ? $array[0] : $this->router->config('default_action');
if (!empty($array[1])) { if (!empty($array[1])) {
$this->parseUrlParams($array[1]); $this->parseUrlParams($request, $array[1]);
} }
return new CallbackDispatch([$class, $action]); return new CallbackDispatch($request, $this->router, [$class, $action]);
} }
/** /**
* 绑定到命名空间 * 绑定到命名空间
* @access protected * @access protected
* @param Request $request
* @param string $url URL地址 * @param string $url URL地址
* @param string $namespace 命名空间 * @param string $namespace 命名空间
* @return CallbackDispatch * @return CallbackDispatch
*/ */
protected function bindToNamespace($url, $namespace) protected function bindToNamespace($request, $url, $namespace)
{ {
$array = explode('|', $url, 3); $array = explode('|', $url, 3);
$class = !empty($array[0]) ? $array[0] : Container::get('config')->get('default_controller'); $class = !empty($array[0]) ? $array[0] : $this->router->config('default_controller');
$method = !empty($array[1]) ? $array[1] : Container::get('config')->get('default_action'); $method = !empty($array[1]) ? $array[1] : $this->router->config('default_action');
if (!empty($array[2])) { if (!empty($array[2])) {
$this->parseUrlParams($array[2]); $this->parseUrlParams($request, $array[2]);
} }
return new CallbackDispatch([$namespace . '\\' . Loader::parseName($class, 1), $method]); return new CallbackDispatch($request, $this->router, [$namespace . '\\' . Loader::parseName($class, 1), $method]);
} }
/** /**
* 绑定到控制器类 * 绑定到控制器类
* @access protected * @access protected
* @param Request $request
* @param string $url URL地址 * @param string $url URL地址
* @param string $controller 控制器名 (支持带模块名 index/user * @param string $controller 控制器名 (支持带模块名 index/user
* @return ControllerDispatch * @return ControllerDispatch
*/ */
protected function bindToController($url, $controller) protected function bindToController($request, $url, $controller)
{ {
$array = explode('|', $url, 2); $array = explode('|', $url, 2);
$action = !empty($array[0]) ? $array[0] : Container::get('config')->get('default_action'); $action = !empty($array[0]) ? $array[0] : $this->router->config('default_action');
if (!empty($array[1])) { if (!empty($array[1])) {
$this->parseUrlParams($array[1]); $this->parseUrlParams($request, $array[1]);
} }
return new ControllerDispatch($controller . '/' . $action); return new ControllerDispatch($request, $this->router, $controller . '/' . $action);
} }
/** /**
* 绑定到模块/控制器 * 绑定到模块/控制器
* @access protected * @access protected
* @param Request $request
* @param string $url URL地址 * @param string $url URL地址
* @param string $controller 控制器类名(带命名空间) * @param string $controller 控制器类名(带命名空间)
* @return ModuleDispatch * @return ModuleDispatch
*/ */
protected function bindToModule($url, $controller) protected function bindToModule($request, $url, $controller)
{ {
$array = explode('|', $url, 2); $array = explode('|', $url, 2);
$action = !empty($array[0]) ? $array[0] : Container::get('config')->get('default_action'); $action = !empty($array[0]) ? $array[0] : $this->router->config('default_action');
if (!empty($array[1])) { if (!empty($array[1])) {
$this->parseUrlParams($array[1]); $this->parseUrlParams($request, $array[1]);
} }
return new ModuleDispatch($controller . '/' . $action); return new ModuleDispatch($request, $this->router, $controller . '/' . $action);
} }
} }

View File

@ -12,7 +12,6 @@
namespace think\route; namespace think\route;
use think\Container; use think\Container;
use think\exception\ValidateException;
use think\Request; use think\Request;
use think\Response; use think\Response;
use think\route\dispatch\Callback as CallbackDispatch; use think\route\dispatch\Callback as CallbackDispatch;
@ -122,6 +121,27 @@ abstract class Rule
return isset($this->pattern[$name]) ? $this->pattern[$name] : null; return isset($this->pattern[$name]) ? $this->pattern[$name] : null;
} }
/**
* 获取路由参数
* @access public
* @param string $name 变量名
* @return mixed
*/
public function getConfig($name = '')
{
return $this->router->config($name);
}
/**
* 获取路由对象
* @access public
* @return Route
*/
public function getRouter()
{
return $this->router;
}
/** /**
* 获取路由参数定义 * 获取路由参数定义
* @access public * @access public
@ -485,7 +505,7 @@ abstract class Rule
$this->option['header'] = $header; $this->option['header'] = $header;
if ($request->method(true) == 'OPTIONS') { if ($request->method(true) == 'OPTIONS') {
return new ResponseDispatch(Response::create()->code(204)->header($header)); return new ResponseDispatch($request, $this, Response::create()->code(204)->header($header));
} }
} }
} }
@ -528,73 +548,6 @@ abstract class Rule
return $this->option; return $this->option;
} }
/**
* 路由绑定模型实例
* @access protected
* @param array|\Clousre $bindModel 绑定模型
* @param array $matches 路由变量
* @return void
*/
protected function createBindModel($bindModel, $matches)
{
foreach ($bindModel as $key => $val) {
if ($val instanceof \Closure) {
$result = Container::getInstance()->invokeFunction($val, $matches);
} else {
$fields = explode('&', $key);
if (is_array($val)) {
list($model, $exception) = $val;
} else {
$model = $val;
$exception = true;
}
$where = [];
$match = true;
foreach ($fields as $field) {
if (!isset($matches[$field])) {
$match = false;
break;
} else {
$where[] = [$field, '=', $matches[$field]];
}
}
if ($match) {
$query = strpos($model, '\\') ? $model::where($where) : Container::get('app')->model($model)->where($where);
$result = $query->failException($exception)->find();
}
}
if (!empty($result)) {
// 注入容器
Container::getInstance()->instance(get_class($result), $result);
}
}
}
/**
* 处理路由请求缓存
* @access protected
* @param Request $request 请求对象
* @param string|array $cache 路由缓存
* @return void
*/
protected function parseRequestCache($request, $cache)
{
if (is_array($cache)) {
list($key, $expire, $tag) = array_pad($cache, 3, null);
} else {
$key = str_replace('|', '/', $request->url());
$expire = $cache;
$tag = null;
}
$request->cache($key, $expire, $tag);
}
/** /**
* 解析匹配到的规则路由 * 解析匹配到的规则路由
* @access public * @access public
@ -624,107 +577,19 @@ abstract class Rule
} }
} }
$this->afterMatchRule($request, $option, $matches);
// 解析额外参数 // 解析额外参数
$count = substr_count($rule, '/'); $count = substr_count($rule, '/');
$url = array_slice(explode('|', $url), $count + 1); $url = array_slice(explode('|', $url), $count + 1);
$this->parseUrlParams(implode('|', $url), $matches); $this->parseUrlParams($request, implode('|', $url), $matches);
// 记录匹配的路由信息 $this->route = $route;
$request->routeInfo(['rule' => $rule, 'route' => $route, 'option' => $option, 'var' => $matches]); $this->vars = $matches;
$this->option = $option;
// 检测路由after行为
if (!empty($option['after'])) {
$dispatch = $this->checkAfter($option['after']);
if (false !== $dispatch) {
return $dispatch;
}
}
// 数据自动验证
if (isset($option['validate'])) {
$this->autoValidate($option['validate'], $request);
}
// 发起路由调度 // 发起路由调度
return $this->dispatch($request, $route, $option); return $this->dispatch($request, $route, $option);
} }
protected function afterMatchRule($request, $option = [], $matches = [])
{
// 添加中间件
if (!empty($option['middleware'])) {
Container::get('middleware')->import($option['middleware']);
}
// 绑定模型数据
if (!empty($option['model'])) {
$this->createBindModel($option['model'], $matches);
}
// 指定Header数据
if (!empty($option['header'])) {
$header = $option['header'];
Container::get('hook')->add('response_send', function ($response) use ($header) {
$response->header($header);
});
}
// 指定Response响应数据
if (!empty($option['response'])) {
Container::get('hook')->add('response_send', $option['response']);
}
// 开启请求缓存
if (isset($option['cache']) && $request->isGet()) {
$this->parseRequestCache($request, $option['cache']);
}
if (!empty($option['append'])) {
$request->route($option['append']);
}
}
/**
* 验证数据
* @access protected
* @param array $option
* @param \think\Request $request
* @return void
* @throws ValidateException
*/
protected function autoValidate($option, $request)
{
list($validate, $scene, $message, $batch) = $option;
if (is_array($validate)) {
// 指定验证规则
$v = Container::get('app')->validate();
$v->rule($validate);
} else {
// 调用验证器
$v = Container::get('app')->validate($validate);
if (!empty($scene)) {
$v->scene($scene);
}
}
if (!empty($message)) {
$v->message($message);
}
// 批量验证
if ($batch) {
$v->batch(true);
}
if (!$v->check($request->param())) {
throw new ValidateException($v->getError());
}
}
/** /**
* 检查路由前置行为 * 检查路由前置行为
* @access protected * @access protected
@ -744,38 +609,6 @@ abstract class Rule
} }
} }
/**
* 检查路由后置行为
* @access protected
* @param mixed $after 后置行为
* @return mixed
*/
protected function checkAfter($after)
{
Container::get('log')->notice('路由后置行为建议使用中间件替代!');
$hook = Container::get('hook');
$result = null;
foreach ((array) $after as $behavior) {
$result = $hook->exec($behavior);
if (!is_null($result)) {
break;
}
}
// 路由规则重定向
if ($result instanceof Response) {
return new ResponseDispatch($result);
} elseif ($result instanceof Dispatch) {
return $result;
}
return false;
}
/** /**
* 发起路由调度 * 发起路由调度
* @access protected * @access protected
@ -788,17 +621,17 @@ abstract class Rule
{ {
if ($route instanceof \Closure) { if ($route instanceof \Closure) {
// 执行闭包 // 执行闭包
$result = new CallbackDispatch($route); $result = new CallbackDispatch($request, $this, $route);
} elseif ($route instanceof Response) { } elseif ($route instanceof Response) {
$result = new ResponseDispatch($route); $result = new ResponseDispatch($request, $this, $route);
} elseif (isset($option['view']) && false !== $option['view']) { } elseif (isset($option['view']) && false !== $option['view']) {
$result = new ViewDispatch($route, is_array($option['view']) ? $option['view'] : []); $result = new ViewDispatch($request, $this, $route, is_array($option['view']) ? $option['view'] : []);
} elseif (!empty($option['redirect']) || 0 === strpos($route, '/') || strpos($route, '://')) { } elseif (!empty($option['redirect']) || 0 === strpos($route, '/') || strpos($route, '://')) {
// 路由到重定向地址 // 路由到重定向地址
$result = new RedirectDispatch($route, [], isset($option['status']) ? $option['status'] : 301); $result = new RedirectDispatch($request, $this, $route, [], isset($option['status']) ? $option['status'] : 301);
} elseif (false !== strpos($route, '\\')) { } elseif (false !== strpos($route, '\\')) {
// 路由到方法 // 路由到方法
$result = $this->dispatchMethod($route); $result = $this->dispatchMethod($request, $route);
} elseif (0 === strpos($route, '@')) { } elseif (0 === strpos($route, '@')) {
// 路由到控制器 // 路由到控制器
$result = $this->dispatchController($request, substr($route, 1)); $result = $this->dispatchController($request, substr($route, 1));
@ -813,17 +646,18 @@ abstract class Rule
/** /**
* 解析URL地址为 模块/控制器/操作 * 解析URL地址为 模块/控制器/操作
* @access protected * @access protected
* @param Request $request Request对象
* @param string $route 路由地址 * @param string $route 路由地址
* @return CallbackDispatch * @return CallbackDispatch
*/ */
protected function dispatchMethod($route) protected function dispatchMethod($request, $route)
{ {
list($path, $var) = $this->parseUrlPath($route); list($path, $var) = $this->parseUrlPath($route);
$route = str_replace('/', '@', implode('/', $path)); $route = str_replace('/', '@', implode('/', $path));
$method = strpos($route, '@') ? explode('@', $route) : $route; $method = strpos($route, '@') ? explode('@', $route) : $route;
return new CallbackDispatch($method, $var); return new CallbackDispatch($request, $this, $method, $var);
} }
/** /**
@ -837,13 +671,11 @@ abstract class Rule
{ {
list($route, $var) = $this->parseUrlPath($route); list($route, $var) = $this->parseUrlPath($route);
$result = new ControllerDispatch(implode('/', $route), $var); $result = new ControllerDispatch($request, $this, implode('/', $route), $var);
$request->action(array_pop($route)); $request->action(array_pop($route));
$app = Container::get('app'); $request->controller($route ? array_pop($route) : $this->getConfig('default_controller'));
$request->controller($route ? array_pop($route) : $app->config('default_controller')); $request->module($route ? array_pop($route) : $this->getConfig('default_module'));
$request->module($route ? array_pop($route) : $app->config('default_module'));
$app->setModulePath($app->getAppPath() . ($app->config('app_multi_module') ? $request->module() . DIRECTORY_SEPARATOR : ''));
return $result; return $result;
} }
@ -859,13 +691,12 @@ abstract class Rule
{ {
list($path, $var) = $this->parseUrlPath($route); list($path, $var) = $this->parseUrlPath($route);
$config = Container::get('config');
$action = array_pop($path); $action = array_pop($path);
$controller = !empty($path) ? array_pop($path) : null; $controller = !empty($path) ? array_pop($path) : null;
$module = $config->get('app_multi_module') && !empty($path) ? array_pop($path) : null; $module = $this->getConfig('app_multi_module') && !empty($path) ? array_pop($path) : null;
$method = $request->method(); $method = $request->method();
if ($config->get('use_action_prefix') && $this->router->getMethodPrefix($method)) { if ($this->getConfig('use_action_prefix') && $this->router->getMethodPrefix($method)) {
$prefix = $this->router->getMethodPrefix($method); $prefix = $this->router->getMethodPrefix($method);
// 操作方法前缀支持 // 操作方法前缀支持
$action = 0 !== strpos($action, $prefix) ? $prefix . $action : $action; $action = 0 !== strpos($action, $prefix) ? $prefix . $action : $action;
@ -875,7 +706,7 @@ abstract class Rule
$request->route($var); $request->route($var);
// 路由到模块/控制器/操作 // 路由到模块/控制器/操作
return new ModuleDispatch([$module, $controller, $action], [], false); return new ModuleDispatch($request, $this, [$module, $controller, $action], ['convert' => false]);
} }
/** /**
@ -927,14 +758,15 @@ abstract class Rule
/** /**
* 解析URL地址中的参数Request对象 * 解析URL地址中的参数Request对象
* @access protected * @access protected
* @param Request $request
* @param string $rule 路由规则 * @param string $rule 路由规则
* @param array $var 变量 * @param array $var 变量
* @return void * @return void
*/ */
protected function parseUrlParams($url, &$var = []) protected function parseUrlParams($request, $url, &$var = [])
{ {
if ($url) { if ($url) {
if (Container::get('config')->get('url_param_type')) { if ($this->getConfig('url_param_type')) {
$var += explode('|', $url); $var += explode('|', $url);
} else { } else {
preg_replace_callback('/(\w+)\|([^\|]+)/', function ($match) use (&$var) { preg_replace_callback('/(\w+)\|([^\|]+)/', function ($match) use (&$var) {
@ -944,7 +776,7 @@ abstract class Rule
} }
// 设置当前请求的参数 // 设置当前请求的参数
Container::get('request')->route($var); $request->route($var);
} }
/** /**
@ -1053,7 +885,7 @@ abstract class Rule
$nameRule = substr($nameRule, 1, -1); $nameRule = substr($nameRule, 1, -1);
} }
} else { } else {
$nameRule = '\w+'; $nameRule = $this->getConfig('default_route_pattern');
} }
return '(' . $prefix . '(?<' . $name . $suffix . '>' . $nameRule . '))' . $optional; return '(' . $prefix . '(?<' . $name . $suffix . '>' . $nameRule . '))' . $optional;

View File

@ -111,11 +111,10 @@ class RuleGroup extends Rule
* @access public * @access public
* @param Request $request 请求对象 * @param Request $request 请求对象
* @param string $url 访问地址 * @param string $url 访问地址
* @param string $depr 路径分隔符
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return Dispatch|false * @return Dispatch|false
*/ */
public function check($request, $url, $depr = '/', $completeMatch = false) public function check($request, $url, $completeMatch = false)
{ {
if ($dispatch = $this->checkCrossDomain($request)) { if ($dispatch = $this->checkCrossDomain($request)) {
// 跨域OPTIONS请求 // 跨域OPTIONS请求
@ -132,7 +131,7 @@ class RuleGroup extends Rule
$this->buildResourceRule($this->resource, $this->option); $this->buildResourceRule($this->resource, $this->option);
} elseif ($this->rule) { } elseif ($this->rule) {
if ($this->rule instanceof Response) { if ($this->rule instanceof Response) {
return new ResponseDispatch($this->rule); return new ResponseDispatch($request, $this->router, $this->rule);
} }
$this->parseGroupRule($this->rule); $this->parseGroupRule($this->rule);
@ -159,7 +158,7 @@ class RuleGroup extends Rule
if (!empty($this->option['merge_rule_regex'])) { if (!empty($this->option['merge_rule_regex'])) {
// 合并路由正则规则进行路由匹配检查 // 合并路由正则规则进行路由匹配检查
$result = $this->checkMergeRuleRegex($request, $rules, $url, $depr, $completeMatch); $result = $this->checkMergeRuleRegex($request, $rules, $url, $completeMatch);
if (false !== $result) { if (false !== $result) {
return $result; return $result;
@ -168,7 +167,7 @@ class RuleGroup extends Rule
// 检查分组路由 // 检查分组路由
foreach ($rules as $key => $item) { foreach ($rules as $key => $item) {
$result = $item->check($request, $url, $depr, $completeMatch); $result = $item->check($request, $url, $completeMatch);
if (false !== $result) { if (false !== $result) {
return $result; return $result;
@ -177,10 +176,12 @@ class RuleGroup extends Rule
if ($this->auto) { if ($this->auto) {
// 自动解析URL地址 // 自动解析URL地址
$result = new UrlDispatch($this->auto . '/' . $url, ['depr' => $depr, 'auto_search' => false]); $ruleItem = new RuleItem($this->router, $this, '', '', $this->auto . '/' . $url);
$result = new UrlDispatch($request, $ruleItem, $this->auto . '/' . $url, ['auto_search' => false]);
} elseif ($this->miss && in_array($this->miss->getMethod(), ['*', $method])) { } elseif ($this->miss && in_array($this->miss->getMethod(), ['*', $method])) {
// 未匹配所有路由的路由规则处理 // 未匹配所有路由的路由规则处理
$result = $this->parseRule($request, '', $this->miss->getRoute(), $url, $this->miss->getOption()); $ruleItem = new RuleItem($this->router, $this, '', '', $this->miss->getRoute());
$result = $ruleItem->parseRule($request, '', $this->miss->getRoute(), $url, $this->miss->getOption());
} else { } else {
$result = false; $result = false;
} }
@ -268,13 +269,13 @@ class RuleGroup extends Rule
* @param Request $request 请求对象 * @param Request $request 请求对象
* @param array $rules 路由规则 * @param array $rules 路由规则
* @param string $url 访问地址 * @param string $url 访问地址
* @param string $depr 路径分隔符
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return Dispatch|false * @return Dispatch|false
*/ */
protected function checkMergeRuleRegex($request, &$rules, $url, $depr, $completeMatch) protected function checkMergeRuleRegex($request, &$rules, $url, $completeMatch)
{ {
$url = $depr . str_replace('|', $depr, $url); $depr = $this->router->config('pathinfo_depr');
$url = $depr . str_replace('|', $depr, $url);
foreach ($rules as $key => $item) { foreach ($rules as $key => $item) {
if ($item instanceof RuleItem) { if ($item instanceof RuleItem) {

View File

@ -35,6 +35,12 @@ class RuleItem extends Rule
*/ */
protected $method; protected $method;
/**
* 路由变量
* @var array
*/
protected $vars = [];
/** /**
* 架构函数 * 架构函数
* @access public * @access public
@ -125,6 +131,16 @@ class RuleItem extends Rule
return strtolower($this->method); return strtolower($this->method);
} }
/**
* 获取当前路由的变量
* @access public
* @return array
*/
public function getVars()
{
return $this->vars;
}
/** /**
* 检查后缀 * 检查后缀
* @access public * @access public
@ -185,11 +201,10 @@ class RuleItem extends Rule
* @param Request $request 请求对象 * @param Request $request 请求对象
* @param string $url 访问地址 * @param string $url 访问地址
* @param array $match 匹配路由变量 * @param array $match 匹配路由变量
* @param string $depr 路径分隔符
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return Dispatch|false * @return Dispatch|false
*/ */
public function checkRule($request, $url, $match = null, $depr = '/', $completeMatch = false) public function checkRule($request, $url, $match = null, $completeMatch = false)
{ {
if ($dispatch = $this->checkCrossDomain($request)) { if ($dispatch = $this->checkCrossDomain($request)) {
// 允许跨域 // 允许跨域
@ -212,7 +227,7 @@ class RuleItem extends Rule
$url = $this->urlSuffixCheck($request, $url, $option); $url = $this->urlSuffixCheck($request, $url, $option);
if (is_null($match)) { if (is_null($match)) {
$match = $this->match($url, $option, $depr, $completeMatch); $match = $this->match($url, $option, $completeMatch);
} }
if (false !== $match) { if (false !== $match) {
@ -231,9 +246,9 @@ class RuleItem extends Rule
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return Dispatch|false * @return Dispatch|false
*/ */
public function check($request, $url, $depr = '/', $completeMatch = false) public function check($request, $url, $completeMatch = false)
{ {
return $this->checkRule($request, $url, null, $depr, $completeMatch); return $this->checkRule($request, $url, null, $completeMatch);
} }
/** /**
@ -265,11 +280,10 @@ class RuleItem extends Rule
* @access private * @access private
* @param string $url URL地址 * @param string $url URL地址
* @param array $option 路由参数 * @param array $option 路由参数
* @param string $depr URL分隔符全局
* @param bool $completeMatch 路由是否完全匹配 * @param bool $completeMatch 路由是否完全匹配
* @return array|false * @return array|false
*/ */
private function match($url, $option, $depr, $completeMatch) private function match($url, $option, $completeMatch)
{ {
if (isset($option['complete_match'])) { if (isset($option['complete_match'])) {
$completeMatch = $option['complete_match']; $completeMatch = $option['complete_match'];
@ -283,6 +297,7 @@ class RuleItem extends Rule
} }
$var = []; $var = [];
$depr = $this->router->config('pathinfo_depr');
$url = $depr . str_replace('|', $depr, $url); $url = $depr . str_replace('|', $depr, $url);
$rule = $depr . str_replace('/', $depr, $this->rule); $rule = $depr . str_replace('/', $depr, $this->rule);

View File

@ -11,17 +11,16 @@
namespace think\route\dispatch; namespace think\route\dispatch;
use think\Container;
use think\route\Dispatch; use think\route\Dispatch;
class Callback extends Dispatch class Callback extends Dispatch
{ {
public function run() public function exec()
{ {
// 执行回调方法 // 执行回调方法
$vars = array_merge($this->app['request']->param(), $this->param); $vars = array_merge($this->request->param(), $this->param);
return Container::getInstance()->invoke($this->dispatch, $vars); return $this->app->invoke($this->dispatch, $vars);
} }
} }

View File

@ -15,15 +15,15 @@ use think\route\Dispatch;
class Controller extends Dispatch class Controller extends Dispatch
{ {
public function run() public function exec()
{ {
// 执行控制器的操作方法 // 执行控制器的操作方法
$vars = array_merge($this->app['request']->param(), $this->param); $vars = array_merge($this->request->param(), $this->param);
return $this->app->action( return $this->app->action(
$this->dispatch, $vars, $this->dispatch, $vars,
$this->app->config('app.url_controller_layer'), $this->router->getConfig('url_controller_layer'),
$this->app->config('app.controller_suffix') $this->router->getConfig('controller_suffix')
); );
} }

View File

@ -12,7 +12,6 @@
namespace think\route\dispatch; namespace think\route\dispatch;
use ReflectionMethod; use ReflectionMethod;
use think\Container;
use think\exception\ClassNotFoundException; use think\exception\ClassNotFoundException;
use think\exception\HttpException; use think\exception\HttpException;
use think\Loader; use think\Loader;
@ -23,15 +22,6 @@ class Module extends Dispatch
protected $controller; protected $controller;
protected $actionName; protected $actionName;
public function __construct($dispatch, $param = [], $convert = null)
{
$this->app = Container::get('app');
$this->dispatch = $dispatch;
$this->param = $param;
$this->convert = $convert;
$this->init();
}
protected function init() protected function init()
{ {
$result = $this->dispatch; $result = $this->dispatch;
@ -40,10 +30,10 @@ class Module extends Dispatch
$result = explode('/', $result); $result = explode('/', $result);
} }
if ($this->app->config('app.app_multi_module')) { if ($this->router->getConfig('app_multi_module')) {
// 多模块部署 // 多模块部署
$module = strip_tags(strtolower($result[0] ?: $this->app->config('app.default_module'))); $module = strip_tags(strtolower($result[0] ?: $this->router->getConfig('default_module')));
$bind = $this->app['route']->getBind(); $bind = $this->router->getRouter()->getBind();
$available = false; $available = false;
if ($bind && preg_match('/^[a-z]/is', $bind)) { if ($bind && preg_match('/^[a-z]/is', $bind)) {
@ -53,48 +43,38 @@ class Module extends Dispatch
$module = $bindModule; $module = $bindModule;
} }
$available = true; $available = true;
} elseif (!in_array($module, $this->app->config('app.deny_module_list')) && is_dir($this->app->getAppPath() . $module)) { } elseif (!in_array($module, $this->router->getConfig('deny_module_list')) && is_dir($this->app->getAppPath() . $module)) {
$available = true; $available = true;
} elseif ($this->app->config('app.empty_module')) { } elseif ($this->router->getConfig('empty_module')) {
$module = $this->app->config('app.empty_module'); $module = $this->router->getConfig('empty_module');
$available = true; $available = true;
} }
// 模块初始化 // 模块初始化
if ($module && $available) { if ($module && $available) {
// 初始化模块 // 初始化模块
$this->app['request']->module($module); $this->request->module($module);
$this->app->init($module); $this->app->init($module);
// 加载当前模块语言包
$this->app['lang']->load($this->app->getAppPath() . $module . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR . $this->app['request']->langset() . '.php');
// 模块请求缓存检查
$this->app['request']->cache(
$this->app->config('app.request_cache'),
$this->app->config('app.request_cache_expire'),
$this->app->config('app.request_cache_except')
);
} else { } else {
throw new HttpException(404, 'module not exists:' . $module); throw new HttpException(404, 'module not exists:' . $module);
} }
} }
// 是否自动转换控制器和操作名 // 是否自动转换控制器和操作名
$convert = is_bool($this->convert) ? $this->convert : $this->app->config('app.url_convert'); $convert = is_bool($this->convert) ? $this->convert : $this->router->getConfig('url_convert');
// 获取控制器名 // 获取控制器名
$controller = strip_tags($result[1] ?: $this->app->config('app.default_controller')); $controller = strip_tags($result[1] ?: $this->router->getConfig('default_controller'));
$this->controller = $convert ? strtolower($controller) : $controller; $this->controller = $convert ? strtolower($controller) : $controller;
// 获取操作名 // 获取操作名
$this->actionName = strip_tags($result[2] ?: $this->app->config('app.default_action')); $this->actionName = strip_tags($result[2] ?: $this->router->getConfig('default_action'));
// 设置当前请求的控制器、操作 // 设置当前请求的控制器、操作
$this->app['request']->controller(Loader::parseName($this->controller, 1))->action($this->actionName); $this->request->controller(Loader::parseName($this->controller, 1))->action($this->actionName);
} }
public function run() public function exec()
{ {
// 监听module_init // 监听module_init
$this->app['hook']->listen('module_init'); $this->app['hook']->listen('module_init');
@ -102,15 +82,15 @@ class Module extends Dispatch
// 实例化控制器 // 实例化控制器
try { try {
$instance = $this->app->controller($this->controller, $instance = $this->app->controller($this->controller,
$this->app->config('app.url_controller_layer'), $this->router->getConfig('url_controller_layer'),
$this->app->config('app.controller_suffix'), $this->router->getConfig('controller_suffix'),
$this->app->config('app.empty_controller')); $this->router->getConfig('empty_controller'));
} catch (ClassNotFoundException $e) { } catch (ClassNotFoundException $e) {
throw new HttpException(404, 'controller not exists:' . $e->getClass()); throw new HttpException(404, 'controller not exists:' . $e->getClass());
} }
// 获取当前操作名 // 获取当前操作名
$action = $this->actionName . $this->app->config('app.action_suffix'); $action = $this->actionName . $this->router->getConfig('action_suffix');
if (is_callable([$instance, $action])) { if (is_callable([$instance, $action])) {
// 执行操作方法 // 执行操作方法
@ -119,14 +99,14 @@ class Module extends Dispatch
// 严格获取当前操作方法名 // 严格获取当前操作方法名
$reflect = new ReflectionMethod($instance, $action); $reflect = new ReflectionMethod($instance, $action);
$methodName = $reflect->getName(); $methodName = $reflect->getName();
$suffix = $this->app->config('app.action_suffix'); $suffix = $this->router->getConfig('action_suffix');
$actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName; $actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName;
$this->app['request']->action($actionName); $this->request->action($actionName);
// 自动获取请求变量 // 自动获取请求变量
$vars = $this->app->config('app.url_param_type') $vars = $this->router->getConfig('url_param_type')
? $this->app['request']->route() ? $this->request->route()
: $this->app['request']->param(); : $this->request->param();
} elseif (is_callable([$instance, '_empty'])) { } elseif (is_callable([$instance, '_empty'])) {
// 空操作 // 空操作
$call = [$instance, '_empty']; $call = [$instance, '_empty'];
@ -138,6 +118,7 @@ class Module extends Dispatch
} }
$this->app['hook']->listen('action_begin', $call); $this->app['hook']->listen('action_begin', $call);
return Container::getInstance()->invokeReflectMethod($instance, $reflect, $vars);
return $this->app->invokeReflectMethod($instance, $reflect, $vars);
} }
} }

View File

@ -16,7 +16,7 @@ use think\route\Dispatch;
class Redirect extends Dispatch class Redirect extends Dispatch
{ {
public function run() public function exec()
{ {
return Response::create($this->dispatch, 'redirect')->code($this->code); return Response::create($this->dispatch, 'redirect')->code($this->code);
} }

View File

@ -15,7 +15,7 @@ use think\route\Dispatch;
class Response extends Dispatch class Response extends Dispatch
{ {
public function run() public function exec()
{ {
return $this->dispatch; return $this->dispatch;
} }

View File

@ -20,28 +20,27 @@ class Url extends Dispatch
protected function init() protected function init()
{ {
// 解析默认的URL规则 // 解析默认的URL规则
$url = str_replace($this->param['depr'], '|', $this->dispatch); $depr = $this->router->getConfig('pathinfo_depr');
$result = $this->parseUrl($url); $result = $this->parseUrl($this->dispatch, $depr);
$this->dispatch = new Module($result); $this->dispatch = new Module($this->request, $this->router, $result);
} }
public function run() public function exec()
{ {
return $this->dispatch->run(); return $this->dispatch->exec();
} }
/** /**
* 解析URL地址 * 解析URL地址
* @access protected * @access protected
* @param string $url URL * @param string $url URL
* @param string $depr 分隔符
* @return array * @return array
*/ */
protected function parseUrl($url) protected function parseUrl($url, $depr)
{ {
$router = $this->app['route']; $bind = $this->router->getRouter()->getBind();
$bind = $router->getBind();
$depr = $this->param['depr'];
if (!empty($bind) && preg_match('/^[a-z]/is', $bind)) { if (!empty($bind) && preg_match('/^[a-z]/is', $bind)) {
$bind = str_replace('/', $depr, $bind); $bind = str_replace('/', $depr, $bind);
@ -55,7 +54,7 @@ class Url extends Dispatch
} }
// 解析模块 // 解析模块
$module = $this->app->config('app_multi_module') ? array_shift($path) : null; $module = $this->router->getConfig('app_multi_module') ? array_shift($path) : null;
if ($this->param['auto_search']) { if ($this->param['auto_search']) {
$controller = $this->autoFindController($module, $path); $controller = $this->autoFindController($module, $path);
} else { } else {
@ -68,7 +67,7 @@ class Url extends Dispatch
// 解析额外参数 // 解析额外参数
if ($path) { if ($path) {
if ($this->app['config']->get('url_param_type')) { if ($this->router->getConfig('url_param_type')) {
$var += $path; $var += $path;
} else { } else {
preg_replace_callback('/(\w+)\|([^\|]+)/', function ($match) use (&$var) { preg_replace_callback('/(\w+)\|([^\|]+)/', function ($match) use (&$var) {
@ -77,14 +76,14 @@ class Url extends Dispatch
} }
} }
$panDomain = $this->app['request']->panDomain(); $panDomain = $this->request->panDomain();
if ($panDomain && $key = array_search('*', $var)) { if ($panDomain && $key = array_search('*', $var)) {
// 泛域名赋值 // 泛域名赋值
$var[$key] = $panDomain; $var[$key] = $panDomain;
} }
// 设置当前请求的参数 // 设置当前请求的参数
$this->app['request']->route($var); $this->request->route($var);
// 封装路由 // 封装路由
$route = [$module, $controller, $action]; $route = [$module, $controller, $action];
@ -116,9 +115,7 @@ class Url extends Dispatch
$name2 = strtolower(Loader::parseName($controller, 1) . '/' . $action); $name2 = strtolower(Loader::parseName($controller, 1) . '/' . $action);
} }
$router = $this->app['route']; if ($this->router->getRouter()->getName($name) || $this->router->getRouter()->getName($name2)) {
if ($router->getName($name) || $router->getName($name2)) {
return true; return true;
} }
@ -134,8 +131,8 @@ class Url extends Dispatch
*/ */
protected function autoFindController($module, &$path) protected function autoFindController($module, &$path)
{ {
$dir = $this->app->getAppPath() . ($module ? $module . '/' : '') . $this->app->config('url_controller_layer'); $dir = $this->app->getAppPath() . ($module ? $module . '/' : '') . $this->router->getConfig('url_controller_layer');
$suffix = $this->app->getSuffix() || $this->app->config('controller_suffix') ? ucfirst($this->app->config('url_controller_layer')) : ''; $suffix = $this->app->getSuffix() || $this->router->getConfig('controller_suffix') ? ucfirst($this->router->getConfig('url_controller_layer')) : '';
$item = []; $item = [];
$find = false; $find = false;

View File

@ -16,10 +16,10 @@ use think\route\Dispatch;
class View extends Dispatch class View extends Dispatch
{ {
public function run() public function exec()
{ {
// 渲染模板输出 // 渲染模板输出
$vars = array_merge($this->app['request']->param(), $this->param); $vars = array_merge($this->request->param(), $this->param);
return Response::create($this->dispatch, 'view')->assign($vars); return Response::create($this->dispatch, 'view')->assign($vars);
} }

View File

@ -11,7 +11,7 @@
namespace think\view\driver; namespace think\view\driver;
use think\Container; use think\App;
use think\exception\TemplateNotFoundException; use think\exception\TemplateNotFoundException;
use think\Loader; use think\Loader;
@ -32,10 +32,12 @@ class Php
]; ];
protected $template; protected $template;
protected $app;
protected $content; protected $content;
public function __construct($config = []) public function __construct(App $app, $config = [])
{ {
$this->app = $app;
$this->config = array_merge($this->config, (array) $config); $this->config = array_merge($this->config, (array) $config);
} }
@ -77,7 +79,7 @@ class Php
$this->template = $template; $this->template = $template;
// 记录视图信息 // 记录视图信息
Container::get('app') $this->app
->log('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]'); ->log('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]');
extract($data, EXTR_OVERWRITE); extract($data, EXTR_OVERWRITE);
@ -108,10 +110,10 @@ class Php
private function parseTemplate($template) private function parseTemplate($template)
{ {
if (empty($this->config['view_path'])) { if (empty($this->config['view_path'])) {
$this->config['view_path'] = Container::get('app')->getModulePath() . 'view' . DIRECTORY_SEPARATOR; $this->config['view_path'] = $this->app->getModulePath() . 'view' . DIRECTORY_SEPARATOR;
} }
$request = Container::get('request'); $request = $this->app['request'];
// 获取视图根目录 // 获取视图根目录
if (strpos($template, '@')) { if (strpos($template, '@')) {
@ -124,7 +126,7 @@ class Php
$module = isset($module) ? $module : $request->module(); $module = isset($module) ? $module : $request->module();
$path = $this->config['view_base'] . ($module ? $module . DIRECTORY_SEPARATOR : ''); $path = $this->config['view_base'] . ($module ? $module . DIRECTORY_SEPARATOR : '');
} else { } else {
$path = isset($module) ? Container::get('app')->getAppPath() . $module . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR : $this->config['view_path']; $path = isset($module) ? $this->app->getAppPath() . $module . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR : $this->config['view_path'];
} }
$depr = $this->config['view_depr']; $depr = $this->config['view_depr'];

View File

@ -11,7 +11,7 @@
namespace think\view\driver; namespace think\view\driver;
use think\Container; use think\App;
use think\exception\TemplateNotFoundException; use think\exception\TemplateNotFoundException;
use think\Loader; use think\Loader;
use think\Template; use think\Template;
@ -20,6 +20,8 @@ class Think
{ {
// 模板引擎实例 // 模板引擎实例
private $template; private $template;
private $app;
// 模板引擎参数 // 模板引擎参数
protected $config = [ protected $config = [
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 // 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写
@ -36,14 +38,16 @@ class Think
'tpl_cache' => true, 'tpl_cache' => true,
]; ];
public function __construct($config = []) public function __construct(App $app, $config = [])
{ {
$this->app = $app;
$this->config = array_merge($this->config, (array) $config); $this->config = array_merge($this->config, (array) $config);
if (empty($this->config['view_path'])) { if (empty($this->config['view_path'])) {
$this->config['view_path'] = Container::get('app')->getModulePath() . 'view' . DIRECTORY_SEPARATOR; $this->config['view_path'] = $app->getModulePath() . 'view' . DIRECTORY_SEPARATOR;
} }
$this->template = new Template($this->config); $this->template = new Template($app, $this->config);
} }
/** /**
@ -83,7 +87,7 @@ class Think
} }
// 记录视图信息 // 记录视图信息
Container::get('app') $this->app
->log('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]'); ->log('[ VIEW ] ' . $template . ' [ ' . var_export(array_keys($data), true) . ' ]');
$this->template->fetch($template, $data, $config); $this->template->fetch($template, $data, $config);
@ -111,7 +115,7 @@ class Think
private function parseTemplate($template) private function parseTemplate($template)
{ {
// 分析模板文件规则 // 分析模板文件规则
$request = Container::get('request'); $request = $this->app['request'];
// 获取视图根目录 // 获取视图根目录
if (strpos($template, '@')) { if (strpos($template, '@')) {
@ -124,7 +128,7 @@ class Think
$module = isset($module) ? $module : $request->module(); $module = isset($module) ? $module : $request->module();
$path = $this->config['view_base'] . ($module ? $module . DIRECTORY_SEPARATOR : ''); $path = $this->config['view_base'] . ($module ? $module . DIRECTORY_SEPARATOR : '');
} else { } else {
$path = isset($module) ? Container::get('app')->getAppPath() . $module . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR : $this->config['view_path']; $path = isset($module) ? $this->app->getAppPath() . $module . DIRECTORY_SEPARATOR . 'view' . DIRECTORY_SEPARATOR : $this->config['view_path'];
} }
$depr = $this->config['view_depr']; $depr = $this->config['view_depr'];

View File

@ -20,6 +20,12 @@ use think\response\Redirect;
trait Jump trait Jump
{ {
/**
* 应用实例
* @var \think\App
*/
protected $app;
/** /**
* 操作成功跳转的快捷方法 * 操作成功跳转的快捷方法
* @access protected * @access protected
@ -52,7 +58,7 @@ trait Jump
$type = 'jump'; $type = 'jump';
} }
$response = Response::create($result, $type)->header($header)->options(['jump_template' => Container::get('config')->get('dispatch_success_tmpl')]); $response = Response::create($result, $type)->header($header)->options(['jump_template' => $this->app['config']->get('dispatch_success_tmpl')]);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }
@ -69,10 +75,11 @@ trait Jump
*/ */
protected function error($msg = '', $url = null, $data = '', $wait = 3, array $header = []) protected function error($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
{ {
$type = $this->getResponseType();
if (is_null($url)) { if (is_null($url)) {
$url = Container::get('request')->isAjax() ? '' : 'javascript:history.back(-1);'; $url = $this->app['request']->isAjax() ? '' : 'javascript:history.back(-1);';
} elseif ('' !== $url) { } elseif ('' !== $url) {
$url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : Container::get('url')->build($url); $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : $this->app['url']->build($url);
} }
$result = [ $result = [
@ -83,12 +90,11 @@ trait Jump
'wait' => $wait, 'wait' => $wait,
]; ];
$type = $this->getResponseType();
if ('html' == strtolower($type)) { if ('html' == strtolower($type)) {
$type = 'jump'; $type = 'jump';
} }
$response = Response::create($result, $type)->header($header)->options(['jump_template' => Container::get('config')->get('dispatch_error_tmpl')]); $response = Response::create($result, $type)->header($header)->options(['jump_template' => $this->app['config']->get('dispatch_error_tmpl')]);
throw new HttpResponseException($response); throw new HttpResponseException($response);
} }
@ -148,8 +154,12 @@ trait Jump
*/ */
protected function getResponseType() protected function getResponseType()
{ {
$isAjax = Container::get('request')->isAjax(); if (!$this->app) {
$config = Container::get('config'); $this->app = Container::get('app');
}
$isAjax = $this->app['request']->isAjax();
$config = $this->app['config'];
return $isAjax return $isAjax
? $config->get('default_ajax_return') ? $config->get('default_ajax_return')

2
vendor/autoload.php vendored
View File

@ -4,4 +4,4 @@
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInitedd8bf4bf1f017c1edc90ff3c3c5de3c::getLoader(); return ComposerAutoloaderInit513ee155225f84554dcc21f55f596f8f::getLoader();

View File

@ -2,7 +2,7 @@
// autoload_real.php @generated by Composer // autoload_real.php @generated by Composer
class ComposerAutoloaderInitedd8bf4bf1f017c1edc90ff3c3c5de3c class ComposerAutoloaderInit513ee155225f84554dcc21f55f596f8f
{ {
private static $loader; private static $loader;
@ -19,15 +19,15 @@ class ComposerAutoloaderInitedd8bf4bf1f017c1edc90ff3c3c5de3c
return self::$loader; return self::$loader;
} }
spl_autoload_register(array('ComposerAutoloaderInitedd8bf4bf1f017c1edc90ff3c3c5de3c', 'loadClassLoader'), true, true); spl_autoload_register(array('ComposerAutoloaderInit513ee155225f84554dcc21f55f596f8f', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(); self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInitedd8bf4bf1f017c1edc90ff3c3c5de3c', 'loadClassLoader')); spl_autoload_unregister(array('ComposerAutoloaderInit513ee155225f84554dcc21f55f596f8f', 'loadClassLoader'));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded()); $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) { if ($useStaticLoader) {
require_once __DIR__ . '/autoload_static.php'; require_once __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c::getInitializer($loader)); call_user_func(\Composer\Autoload\ComposerStaticInit513ee155225f84554dcc21f55f596f8f::getInitializer($loader));
} else { } else {
$map = require __DIR__ . '/autoload_namespaces.php'; $map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) { foreach ($map as $namespace => $path) {
@ -48,19 +48,19 @@ class ComposerAutoloaderInitedd8bf4bf1f017c1edc90ff3c3c5de3c
$loader->register(true); $loader->register(true);
if ($useStaticLoader) { if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c::$files; $includeFiles = Composer\Autoload\ComposerStaticInit513ee155225f84554dcc21f55f596f8f::$files;
} else { } else {
$includeFiles = require __DIR__ . '/autoload_files.php'; $includeFiles = require __DIR__ . '/autoload_files.php';
} }
foreach ($includeFiles as $fileIdentifier => $file) { foreach ($includeFiles as $fileIdentifier => $file) {
composerRequireedd8bf4bf1f017c1edc90ff3c3c5de3c($fileIdentifier, $file); composerRequire513ee155225f84554dcc21f55f596f8f($fileIdentifier, $file);
} }
return $loader; return $loader;
} }
} }
function composerRequireedd8bf4bf1f017c1edc90ff3c3c5de3c($fileIdentifier, $file) function composerRequire513ee155225f84554dcc21f55f596f8f($fileIdentifier, $file)
{ {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) { if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file; require $file;

View File

@ -4,7 +4,7 @@
namespace Composer\Autoload; namespace Composer\Autoload;
class ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c class ComposerStaticInit513ee155225f84554dcc21f55f596f8f
{ {
public static $files = array ( public static $files = array (
'1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php', '1cfd2761b63b0a29ed23657ea394cb2d' => __DIR__ . '/..' . '/topthink/think-captcha/src/helper.php',
@ -287,9 +287,9 @@ class ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c
public static function getInitializer(ClassLoader $loader) public static function getInitializer(ClassLoader $loader)
{ {
return \Closure::bind(function () use ($loader) { return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c::$prefixLengthsPsr4; $loader->prefixLengthsPsr4 = ComposerStaticInit513ee155225f84554dcc21f55f596f8f::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c::$prefixDirsPsr4; $loader->prefixDirsPsr4 = ComposerStaticInit513ee155225f84554dcc21f55f596f8f::$prefixDirsPsr4;
$loader->classMap = ComposerStaticInitedd8bf4bf1f017c1edc90ff3c3c5de3c::$classMap; $loader->classMap = ComposerStaticInit513ee155225f84554dcc21f55f596f8f::$classMap;
}, null, ClassLoader::class); }, null, ClassLoader::class);
} }

View File

@ -178,17 +178,17 @@
}, },
{ {
"name": "topthink/framework", "name": "topthink/framework",
"version": "v5.1.13", "version": "v5.1.14",
"version_normalized": "5.1.13.0", "version_normalized": "5.1.14.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/top-think/framework.git", "url": "https://github.com/top-think/framework.git",
"reference": "1cc81707dab128e360405aa4811a27b7a5403a78" "reference": "1adc81f2d59cd99e69d38c058527cd759531e8a8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://files.phpcomposer.com/files/top-think/framework/1cc81707dab128e360405aa4811a27b7a5403a78.zip", "url": "https://files.phpcomposer.com/files/top-think/framework/1adc81f2d59cd99e69d38c058527cd759531e8a8.zip",
"reference": "1cc81707dab128e360405aa4811a27b7a5403a78", "reference": "1adc81f2d59cd99e69d38c058527cd759531e8a8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -204,7 +204,7 @@
"sebastian/phpcpd": "2.*", "sebastian/phpcpd": "2.*",
"squizlabs/php_codesniffer": "2.*" "squizlabs/php_codesniffer": "2.*"
}, },
"time": "2018-05-11T07:50:00+00:00", "time": "2018-05-19T04:16:33+00:00",
"type": "think-framework", "type": "think-framework",
"installation-source": "dist", "installation-source": "dist",
"notification-url": "https://packagist.org/downloads/", "notification-url": "https://packagist.org/downloads/",
@ -433,17 +433,17 @@
}, },
{ {
"name": "qiniu/php-sdk", "name": "qiniu/php-sdk",
"version": "v7.2.5", "version": "v7.2.6",
"version_normalized": "7.2.5.0", "version_normalized": "7.2.6.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/qiniu/php-sdk.git", "url": "https://github.com/qiniu/php-sdk.git",
"reference": "0a6e6c75cbc0429fac69ba9aaadb1f5d6c676fb0" "reference": "305ce1c1c0c71f794661fe45a96facf61ef96c5d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://files.phpcomposer.com/files/qiniu/php-sdk/0a6e6c75cbc0429fac69ba9aaadb1f5d6c676fb0.zip", "url": "https://files.phpcomposer.com/files/qiniu/php-sdk/305ce1c1c0c71f794661fe45a96facf61ef96c5d.zip",
"reference": "0a6e6c75cbc0429fac69ba9aaadb1f5d6c676fb0", "reference": "305ce1c1c0c71f794661fe45a96facf61ef96c5d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -453,7 +453,7 @@
"phpunit/phpunit": "~4.0", "phpunit/phpunit": "~4.0",
"squizlabs/php_codesniffer": "~2.3" "squizlabs/php_codesniffer": "~2.3"
}, },
"time": "2018-05-10T09:26:30+00:00", "time": "2018-05-18T04:37:29+00:00",
"type": "library", "type": "library",
"installation-source": "dist", "installation-source": "dist",
"autoload": { "autoload": {

View File

@ -1,5 +1,8 @@
# Changelog # Changelog
## 7.2.6 (2018-05-18)
* 修复rsrsf在不同机房默认的https域名
## 7.2.5 (2018-05-10) ## 7.2.5 (2018-05-10)
* 修复表单上传中多余的参数checkCrc导致的fname错位问题 * 修复表单上传中多余的参数checkCrc导致的fname错位问题

View File

@ -1,4 +1,4 @@
# Qiniu Resource Storage SDK for PHP # Qiniu Cloud SDK for PHP
[![doxygen.io](http://doxygen.io/github.com/qiniu/php-sdk/?status.svg)](http://doxygen.io/github.com/qiniu/php-sdk/) [![doxygen.io](http://doxygen.io/github.com/qiniu/php-sdk/?status.svg)](http://doxygen.io/github.com/qiniu/php-sdk/)
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
[![Build Status](https://travis-ci.org/qiniu/php-sdk.svg)](https://travis-ci.org/qiniu/php-sdk) [![Build Status](https://travis-ci.org/qiniu/php-sdk.svg)](https://travis-ci.org/qiniu/php-sdk)

View File

@ -44,8 +44,8 @@ final class Zone
$Zone_z0 = new Zone( $Zone_z0 = new Zone(
array("up.qiniup.com", 'up-jjh.qiniup.com', 'up-xs.qiniup.com'), array("up.qiniup.com", 'up-jjh.qiniup.com', 'up-xs.qiniup.com'),
array('upload.qiniup.com', 'upload-jjh.qiniup.com', 'upload-xs.qiniup.com'), array('upload.qiniup.com', 'upload-jjh.qiniup.com', 'upload-xs.qiniup.com'),
'rs.qiniu.com', 'rs.qbox.me',
'rsf.qiniu.com', 'rsf.qbox.me',
'api.qiniu.com', 'api.qiniu.com',
'iovip.qbox.me' 'iovip.qbox.me'
); );
@ -58,8 +58,8 @@ final class Zone
$Zone_z1 = new Zone( $Zone_z1 = new Zone(
array('up-z1.qiniup.com'), array('up-z1.qiniup.com'),
array('upload-z1.qiniup.com'), array('upload-z1.qiniup.com'),
"rs-z1.qiniu.com", "rs-z1.qbox.me",
"rsf-z1.qiniu.com", "rsf-z1.qbox.me",
"api-z1.qiniu.com", "api-z1.qiniu.com",
"iovip-z1.qbox.me" "iovip-z1.qbox.me"
); );
@ -73,8 +73,8 @@ final class Zone
$Zone_z2 = new Zone( $Zone_z2 = new Zone(
array('up-z2.qiniup.com', 'up-dg.qiniup.com', 'up-fs.qiniup.com'), array('up-z2.qiniup.com', 'up-dg.qiniup.com', 'up-fs.qiniup.com'),
array('upload-z2.qiniup.com', 'upload-dg.qiniup.com', 'upload-fs.qiniup.com'), array('upload-z2.qiniup.com', 'upload-dg.qiniup.com', 'upload-fs.qiniup.com'),
"rs-z2.qiniu.com", "rs-z2.qbox.me",
"rsf-z2.qiniu.com", "rsf-z2.qbox.me",
"api-z2.qiniu.com", "api-z2.qiniu.com",
"iovip-z2.qbox.me" "iovip-z2.qbox.me"
); );
@ -88,8 +88,8 @@ final class Zone
$Zone_na0 = new Zone( $Zone_na0 = new Zone(
array('up-na0.qiniup.com'), array('up-na0.qiniup.com'),
array('upload-na0.qiniup.com'), array('upload-na0.qiniup.com'),
"rs-na0.qiniu.com", "rs-na0.qbox.me",
"rsf-na0.qiniu.com", "rsf-na0.qbox.me",
"api-na0.qiniu.com", "api-na0.qiniu.com",
"iovip-na0.qbox.me" "iovip-na0.qbox.me"
); );
@ -103,8 +103,8 @@ final class Zone
$Zone_as0 = new Zone( $Zone_as0 = new Zone(
array('up-as0.qiniup.com'), array('up-as0.qiniup.com'),
array('upload-as0.qiniup.com'), array('upload-as0.qiniup.com'),
"rs-as0.qiniu.com", "rs-as0.qbox.me",
"rsf-as0.qiniu.com", "rsf-as0.qbox.me",
"api-as0.qiniu.com", "api-as0.qiniu.com",
"iovip-as0.qbox.me" "iovip-as0.qbox.me"
); );
@ -145,24 +145,24 @@ final class Zone
//set specific hosts //set specific hosts
if (strstr($zone->iovipHost, "z1") !== false) { if (strstr($zone->iovipHost, "z1") !== false) {
$zone->rsHost = "rs-z1.qiniu.com"; $zone->rsHost = "rs-z1.qbox.me";
$zone->rsfHost = "rsf-z1.qiniu.com"; $zone->rsfHost = "rsf-z1.qbox.me";
$zone->apiHost = "api-z1.qiniu.com"; $zone->apiHost = "api-z1.qiniu.com";
} elseif (strstr($zone->iovipHost, "z2") !== false) { } elseif (strstr($zone->iovipHost, "z2") !== false) {
$zone->rsHost = "rs-z2.qiniu.com"; $zone->rsHost = "rs-z2.qbox.me";
$zone->rsfHost = "rsf-z2.qiniu.com"; $zone->rsfHost = "rsf-z2.qbox.me";
$zone->apiHost = "api-z2.qiniu.com"; $zone->apiHost = "api-z2.qiniu.com";
} elseif (strstr($zone->iovipHost, "na0") !== false) { } elseif (strstr($zone->iovipHost, "na0") !== false) {
$zone->rsHost = "rs-na0.qiniu.com"; $zone->rsHost = "rs-na0.qbox.me";
$zone->rsfHost = "rsf-na0.qiniu.com"; $zone->rsfHost = "rsf-na0.qbox.me";
$zone->apiHost = "api-na0.qiniu.com"; $zone->apiHost = "api-na0.qiniu.com";
} elseif (strstr($zone->iovipHost, "as0") !== false) { } elseif (strstr($zone->iovipHost, "as0") !== false) {
$zone->rsHost = "rs-as0.qiniu.com"; $zone->rsHost = "rs-as0.qbox.me";
$zone->rsfHost = "rsf-as0.qiniu.com"; $zone->rsfHost = "rsf-as0.qbox.me";
$zone->apiHost = "api-as0.qiniu.com"; $zone->apiHost = "api-as0.qiniu.com";
} else { } else {
$zone->rsHost = "rs.qiniu.com"; $zone->rsHost = "rs.qbox.me";
$zone->rsfHost = "rsf.qiniu.com"; $zone->rsfHost = "rsf.qbox.me";
$zone->apiHost = "api.qiniu.com"; $zone->apiHost = "api.qiniu.com";
} }