991 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			991 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| // +----------------------------------------------------------------------
 | |
| // | ThinkPHP [ WE CAN DO IT JUST THINK ]
 | |
| // +----------------------------------------------------------------------
 | |
| // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
 | |
| // +----------------------------------------------------------------------
 | |
| // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
 | |
| // +----------------------------------------------------------------------
 | |
| // | Author: liu21st <liu21st@gmail.com>
 | |
| // +----------------------------------------------------------------------
 | |
| 
 | |
| namespace think;
 | |
| 
 | |
| use think\exception\RouteNotFoundException;
 | |
| use think\route\AliasRule;
 | |
| use think\route\dispatch\Url as UrlDispatch;
 | |
| use think\route\Domain;
 | |
| use think\route\Resource;
 | |
| use think\route\RuleGroup;
 | |
| use think\route\RuleItem;
 | |
| 
 | |
| class Route
 | |
| {
 | |
|     /**
 | |
|      * REST定义
 | |
|      * @var array
 | |
|      */
 | |
|     protected $rest = [
 | |
|         'index'  => ['get', '', 'index'],
 | |
|         'create' => ['get', '/create', 'create'],
 | |
|         'edit'   => ['get', '/<id>/edit', 'edit'],
 | |
|         'read'   => ['get', '/<id>', 'read'],
 | |
|         'save'   => ['post', '', 'save'],
 | |
|         'update' => ['put', '/<id>', 'update'],
 | |
|         'delete' => ['delete', '/<id>', 'delete'],
 | |
|     ];
 | |
| 
 | |
|     /**
 | |
|      * 请求方法前缀定义
 | |
|      * @var array
 | |
|      */
 | |
|     protected $methodPrefix = [
 | |
|         'get'    => 'get',
 | |
|         'post'   => 'post',
 | |
|         'put'    => 'put',
 | |
|         'delete' => 'delete',
 | |
|         'patch'  => 'patch',
 | |
|     ];
 | |
| 
 | |
|     /**
 | |
|      * 应用对象
 | |
|      * @var App
 | |
|      */
 | |
|     protected $app;
 | |
| 
 | |
|     /**
 | |
|      * 请求对象
 | |
|      * @var Request
 | |
|      */
 | |
|     protected $request;
 | |
| 
 | |
|     /**
 | |
|      * 当前HOST
 | |
|      * @var string
 | |
|      */
 | |
|     protected $host;
 | |
| 
 | |
|     /**
 | |
|      * 当前域名
 | |
|      * @var string
 | |
|      */
 | |
|     protected $domain;
 | |
| 
 | |
|     /**
 | |
|      * 当前分组对象
 | |
|      * @var RuleGroup
 | |
|      */
 | |
|     protected $group;
 | |
| 
 | |
|     /**
 | |
|      * 配置参数
 | |
|      * @var array
 | |
|      */
 | |
|     protected $config = [];
 | |
| 
 | |
|     /**
 | |
|      * 路由绑定
 | |
|      * @var array
 | |
|      */
 | |
|     protected $bind = [];
 | |
| 
 | |
|     /**
 | |
|      * 域名对象
 | |
|      * @var array
 | |
|      */
 | |
|     protected $domains = [];
 | |
| 
 | |
|     /**
 | |
|      * 跨域路由规则
 | |
|      * @var RuleGroup
 | |
|      */
 | |
|     protected $cross;
 | |
| 
 | |
|     /**
 | |
|      * 路由别名
 | |
|      * @var array
 | |
|      */
 | |
|     protected $alias = [];
 | |
| 
 | |
|     /**
 | |
|      * 路由是否延迟解析
 | |
|      * @var bool
 | |
|      */
 | |
|     protected $lazy = true;
 | |
| 
 | |
|     /**
 | |
|      * 路由是否测试模式
 | |
|      * @var bool
 | |
|      */
 | |
|     protected $isTest;
 | |
| 
 | |
|     /**
 | |
|      * (分组)路由规则是否合并解析
 | |
|      * @var bool
 | |
|      */
 | |
|     protected $mergeRuleRegex = true;
 | |
| 
 | |
|     /**
 | |
|      * 路由解析自动搜索多级控制器
 | |
|      * @var bool
 | |
|      */
 | |
|     protected $autoSearchController = true;
 | |
| 
 | |
|     public function __construct(App $app, array $config = [])
 | |
|     {
 | |
|         $this->app     = $app;
 | |
|         $this->request = $app['request'];
 | |
|         $this->config  = $config;
 | |
| 
 | |
|         $this->host = $this->request->host(true) ?: $config['app_host'];
 | |
| 
 | |
|         $this->setDefaultDomain();
 | |
|     }
 | |
| 
 | |
|     public function config($name = null)
 | |
|     {
 | |
|         if (is_null($name)) {
 | |
|             return $this->config;
 | |
|         }
 | |
| 
 | |
|         return isset($this->config[$name]) ? $this->config[$name] : null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 配置
 | |
|      * @access public
 | |
|      * @param  array $config
 | |
|      * @return void
 | |
|      */
 | |
|     public function setConfig(array $config = [])
 | |
|     {
 | |
|         $this->config = array_merge($this->config, array_change_key_case($config));
 | |
|     }
 | |
| 
 | |
|     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
 | |
|      * @param  Request     $request   请求对象实例
 | |
|      * @return void
 | |
|      */
 | |
|     public function setRequest($request)
 | |
|     {
 | |
|         $this->request = $request;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置路由域名及分组(包括资源路由)是否延迟解析
 | |
|      * @access public
 | |
|      * @param  bool     $lazy   路由是否延迟解析
 | |
|      * @return $this
 | |
|      */
 | |
|     public function lazy($lazy = true)
 | |
|     {
 | |
|         $this->lazy = $lazy;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置路由为测试模式
 | |
|      * @access public
 | |
|      * @param  bool     $test   路由是否测试模式
 | |
|      * @return void
 | |
|      */
 | |
|     public function setTestMode($test)
 | |
|     {
 | |
|         $this->isTest = $test;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 检查路由是否为测试模式
 | |
|      * @access public
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isTest()
 | |
|     {
 | |
|         return $this->isTest;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置路由域名及分组(包括资源路由)是否合并解析
 | |
|      * @access public
 | |
|      * @param  bool     $merge   路由是否合并解析
 | |
|      * @return $this
 | |
|      */
 | |
|     public function mergeRuleRegex($merge = true)
 | |
|     {
 | |
|         $this->mergeRuleRegex = $merge;
 | |
|         $this->group->mergeRuleRegex($merge);
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置路由自动解析是否搜索多级控制器
 | |
|      * @access public
 | |
|      * @param  bool     $auto   是否自动搜索多级控制器
 | |
|      * @return $this
 | |
|      */
 | |
|     public function autoSearchController($auto = true)
 | |
|     {
 | |
|         $this->autoSearchController = $auto;
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 初始化默认域名
 | |
|      * @access protected
 | |
|      * @return void
 | |
|      */
 | |
|     protected function setDefaultDomain()
 | |
|     {
 | |
|         // 默认域名
 | |
|         $this->domain = $this->host;
 | |
| 
 | |
|         // 注册默认域名
 | |
|         $domain = new Domain($this, $this->host);
 | |
| 
 | |
|         $this->domains[$this->host] = $domain;
 | |
| 
 | |
|         // 默认分组
 | |
|         $this->group = $domain;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置当前域名
 | |
|      * @access public
 | |
|      * @param  RuleGroup    $group 域名
 | |
|      * @return void
 | |
|      */
 | |
|     public function setGroup(RuleGroup $group)
 | |
|     {
 | |
|         $this->group = $group;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 获取当前分组
 | |
|      * @access public
 | |
|      * @return RuleGroup
 | |
|      */
 | |
|     public function getGroup()
 | |
|     {
 | |
|         return $this->group;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册变量规则
 | |
|      * @access public
 | |
|      * @param  string|array  $name 变量名
 | |
|      * @param  string        $rule 变量规则
 | |
|      * @return $this
 | |
|      */
 | |
|     public function pattern($name, $rule = '')
 | |
|     {
 | |
|         $this->group->pattern($name, $rule);
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册路由参数
 | |
|      * @access public
 | |
|      * @param  string|array  $name  参数名
 | |
|      * @param  mixed         $value 值
 | |
|      * @return $this
 | |
|      */
 | |
|     public function option($name, $value = '')
 | |
|     {
 | |
|         $this->group->option($name, $value);
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册域名路由
 | |
|      * @access public
 | |
|      * @param  string|array  $name 子域名
 | |
|      * @param  mixed         $rule 路由规则
 | |
|      * @param  array         $option 路由参数
 | |
|      * @param  array         $pattern 变量规则
 | |
|      * @return Domain
 | |
|      */
 | |
|     public function domain($name, $rule = '', $option = [], $pattern = [])
 | |
|     {
 | |
|         // 支持多个域名使用相同路由规则
 | |
|         $domainName = is_array($name) ? array_shift($name) : $name;
 | |
| 
 | |
|         if ('*' != $domainName && false === strpos($domainName, '.')) {
 | |
|             $domainName .= '.' . $this->request->rootDomain();
 | |
|         }
 | |
| 
 | |
|         if (!isset($this->domains[$domainName])) {
 | |
|             $domain = (new Domain($this, $domainName, $rule, $option, $pattern))
 | |
|                 ->lazy($this->lazy)
 | |
|                 ->mergeRuleRegex($this->mergeRuleRegex);
 | |
| 
 | |
|             $this->domains[$domainName] = $domain;
 | |
|         } else {
 | |
|             $domain = $this->domains[$domainName];
 | |
|             $domain->parseGroupRule($rule);
 | |
|         }
 | |
| 
 | |
|         if (is_array($name) && !empty($name)) {
 | |
|             $root = $this->request->rootDomain();
 | |
|             foreach ($name as $item) {
 | |
|                 if (false === strpos($item, '.')) {
 | |
|                     $item .= '.' . $root;
 | |
|                 }
 | |
| 
 | |
|                 $this->domains[$item] = $domainName;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // 返回域名对象
 | |
|         return $domain;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 获取域名
 | |
|      * @access public
 | |
|      * @return array
 | |
|      */
 | |
|     public function getDomains()
 | |
|     {
 | |
|         return $this->domains;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置路由绑定
 | |
|      * @access public
 | |
|      * @param  string     $bind 绑定信息
 | |
|      * @param  string     $domain 域名
 | |
|      * @return $this
 | |
|      */
 | |
|     public function bind($bind, $domain = null)
 | |
|     {
 | |
|         $domain = is_null($domain) ? $this->domain : $domain;
 | |
| 
 | |
|         $this->bind[$domain] = $bind;
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 读取路由绑定
 | |
|      * @access public
 | |
|      * @param  string    $domain 域名
 | |
|      * @return string|null
 | |
|      */
 | |
|     public function getBind($domain = null)
 | |
|     {
 | |
|         if (is_null($domain)) {
 | |
|             $domain = $this->domain;
 | |
|         } elseif (true === $domain) {
 | |
|             return $this->bind;
 | |
|         } elseif (false === strpos($domain, '.')) {
 | |
|             $domain .= '.' . $this->request->rootDomain();
 | |
|         }
 | |
| 
 | |
|         $subDomain = $this->request->subDomain();
 | |
| 
 | |
|         if (strpos($subDomain, '.')) {
 | |
|             $name = '*' . strstr($subDomain, '.');
 | |
|         }
 | |
| 
 | |
|         if (isset($this->bind[$domain])) {
 | |
|             $result = $this->bind[$domain];
 | |
|         } elseif (isset($name) && isset($this->bind[$name])) {
 | |
|             $result = $this->bind[$name];
 | |
|         } elseif (!empty($subDomain) && isset($this->bind['*'])) {
 | |
|             $result = $this->bind['*'];
 | |
|         } else {
 | |
|             $result = null;
 | |
|         }
 | |
| 
 | |
|         return $result;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 读取路由标识
 | |
|      * @access public
 | |
|      * @param  string    $name 路由标识
 | |
|      * @param  string    $domain 域名
 | |
|      * @return mixed
 | |
|      */
 | |
|     public function getName($name = null, $domain = null, $method = '*')
 | |
|     {
 | |
|         return $this->app['rule_name']->get($name, $domain, $method);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 读取路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  string    $domain 域名
 | |
|      * @return array
 | |
|      */
 | |
|     public function getRule($rule, $domain = null)
 | |
|     {
 | |
|         if (is_null($domain)) {
 | |
|             $domain = $this->domain;
 | |
|         }
 | |
| 
 | |
|         return $this->app['rule_name']->getRule($rule, $domain);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 读取路由
 | |
|      * @access public
 | |
|      * @param  string    $domain 域名
 | |
|      * @return array
 | |
|      */
 | |
|     public function getRuleList($domain = null)
 | |
|     {
 | |
|         return $this->app['rule_name']->getRuleList($domain);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 批量导入路由标识
 | |
|      * @access public
 | |
|      * @param  array    $name 路由标识
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setName($name)
 | |
|     {
 | |
|         $this->app['rule_name']->import($name);
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 导入配置文件的路由规则
 | |
|      * @access public
 | |
|      * @param  array     $rules 路由规则
 | |
|      * @param  string    $type  请求类型
 | |
|      * @return void
 | |
|      */
 | |
|     public function import(array $rules, $type = '*')
 | |
|     {
 | |
|         // 检查域名部署
 | |
|         if (isset($rules['__domain__'])) {
 | |
|             foreach ($rules['__domain__'] as $key => $rule) {
 | |
|                 $this->domain($key, $rule);
 | |
|             }
 | |
|             unset($rules['__domain__']);
 | |
|         }
 | |
| 
 | |
|         // 检查变量规则
 | |
|         if (isset($rules['__pattern__'])) {
 | |
|             $this->pattern($rules['__pattern__']);
 | |
|             unset($rules['__pattern__']);
 | |
|         }
 | |
| 
 | |
|         // 检查路由别名
 | |
|         if (isset($rules['__alias__'])) {
 | |
|             foreach ($rules['__alias__'] as $key => $val) {
 | |
|                 $this->alias($key, $val);
 | |
|             }
 | |
|             unset($rules['__alias__']);
 | |
|         }
 | |
| 
 | |
|         // 检查资源路由
 | |
|         if (isset($rules['__rest__'])) {
 | |
|             foreach ($rules['__rest__'] as $key => $rule) {
 | |
|                 $this->resource($key, $rule);
 | |
|             }
 | |
|             unset($rules['__rest__']);
 | |
|         }
 | |
| 
 | |
|         // 检查路由规则(包含分组)
 | |
|         foreach ($rules as $key => $val) {
 | |
|             if (is_numeric($key)) {
 | |
|                 $key = array_shift($val);
 | |
|             }
 | |
| 
 | |
|             if (empty($val)) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             if (is_string($key) && 0 === strpos($key, '[')) {
 | |
|                 $key = substr($key, 1, -1);
 | |
|                 $this->group($key, $val);
 | |
|             } elseif (is_array($val)) {
 | |
|                 $this->rule($key, $val[0], $type, $val[1], isset($val[2]) ? $val[2] : []);
 | |
|             } else {
 | |
|                 $this->rule($key, $val, $type);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册路由规则
 | |
|      * @access public
 | |
|      * @param  string    $rule       路由规则
 | |
|      * @param  mixed     $route      路由地址
 | |
|      * @param  string    $method     请求类型
 | |
|      * @param  array     $option     路由参数
 | |
|      * @param  array     $pattern    变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function rule($rule, $route, $method = '*', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->group->addRule($rule, $route, $method, $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置跨域有效路由规则
 | |
|      * @access public
 | |
|      * @param  Rule      $rule      路由规则
 | |
|      * @param  string    $method    请求类型
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setCrossDomainRule($rule, $method = '*')
 | |
|     {
 | |
|         if (!isset($this->cross)) {
 | |
|             $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
 | |
|         }
 | |
| 
 | |
|         $this->cross->addRuleItem($rule, $method);
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 批量注册路由规则
 | |
|      * @access public
 | |
|      * @param  array     $rules      路由规则
 | |
|      * @param  string    $method     请求类型
 | |
|      * @param  array     $option     路由参数
 | |
|      * @param  array     $pattern    变量规则
 | |
|      * @return void
 | |
|      */
 | |
|     public function rules($rules, $method = '*', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         $this->group->addRules($rules, $method, $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册路由分组
 | |
|      * @access public
 | |
|      * @param  string|array      $name       分组名称或者参数
 | |
|      * @param  array|\Closure    $route      分组路由
 | |
|      * @param  array             $option     路由参数
 | |
|      * @param  array             $pattern    变量规则
 | |
|      * @return RuleGroup
 | |
|      */
 | |
|     public function group($name, $route, array $option = [], array $pattern = [])
 | |
|     {
 | |
|         if (is_array($name)) {
 | |
|             $option = $name;
 | |
|             $name   = isset($option['name']) ? $option['name'] : '';
 | |
|         }
 | |
| 
 | |
|         return (new RuleGroup($this, $this->group, $name, $route, $option, $pattern))
 | |
|             ->lazy($this->lazy)
 | |
|             ->mergeRuleRegex($this->mergeRuleRegex);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  mixed     $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function any($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, '*', $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册GET路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  mixed     $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function get($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, 'GET', $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册POST路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  mixed     $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function post($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, 'POST', $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册PUT路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  mixed     $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function put($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, 'PUT', $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册DELETE路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  mixed     $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function delete($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, 'DELETE', $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册PATCH路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  mixed     $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function patch($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, 'PATCH', $option, $pattern);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册资源路由
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  string    $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return Resource
 | |
|      */
 | |
|     public function resource($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return (new Resource($this, $this->group, $rule, $route, $option, $pattern, $this->rest))
 | |
|             ->lazy($this->lazy);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册控制器路由 操作方法对应不同的请求前缀
 | |
|      * @access public
 | |
|      * @param  string    $rule 路由规则
 | |
|      * @param  string    $route 路由地址
 | |
|      * @param  array     $option 路由参数
 | |
|      * @param  array     $pattern 变量规则
 | |
|      * @return RuleGroup
 | |
|      */
 | |
|     public function controller($rule, $route = '', array $option = [], array $pattern = [])
 | |
|     {
 | |
|         $group = new RuleGroup($this, $this->group, $rule, null, $option, $pattern);
 | |
| 
 | |
|         foreach ($this->methodPrefix as $type => $val) {
 | |
|             $group->addRule('<action>', $val . '<action>', $type);
 | |
|         }
 | |
| 
 | |
|         return $group->prefix($route . '/');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册视图路由
 | |
|      * @access public
 | |
|      * @param  string|array $rule 路由规则
 | |
|      * @param  string       $template 路由模板地址
 | |
|      * @param  array        $vars 模板变量
 | |
|      * @param  array        $option 路由参数
 | |
|      * @param  array        $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function view($rule, $template = '', array $vars = [], array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $template, 'GET', $option, $pattern)->view($vars);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册重定向路由
 | |
|      * @access public
 | |
|      * @param  string|array $rule 路由规则
 | |
|      * @param  string       $route 路由地址
 | |
|      * @param  array        $status 状态码
 | |
|      * @param  array        $option 路由参数
 | |
|      * @param  array        $pattern 变量规则
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function redirect($rule, $route = '', $status = 301, array $option = [], array $pattern = [])
 | |
|     {
 | |
|         return $this->rule($rule, $route, '*', $option, $pattern)->redirect()->status($status);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册别名路由
 | |
|      * @access public
 | |
|      * @param  string  $rule 路由别名
 | |
|      * @param  string  $route 路由地址
 | |
|      * @param  array   $option 路由参数
 | |
|      * @return AliasRule
 | |
|      */
 | |
|     public function alias($rule, $route, array $option = [])
 | |
|     {
 | |
|         $aliasRule = new AliasRule($this, $this->group, $rule, $route, $option);
 | |
| 
 | |
|         $this->alias[$rule] = $aliasRule;
 | |
| 
 | |
|         return $aliasRule;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 获取别名路由定义
 | |
|      * @access public
 | |
|      * @param  string    $name 路由别名
 | |
|      * @return string|array|null
 | |
|      */
 | |
|     public function getAlias($name = null)
 | |
|     {
 | |
|         if (is_null($name)) {
 | |
|             return $this->alias;
 | |
|         }
 | |
| 
 | |
|         return isset($this->alias[$name]) ? $this->alias[$name] : null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置不同请求类型下面的方法前缀
 | |
|      * @access public
 | |
|      * @param  string|array  $method 请求类型
 | |
|      * @param  string        $prefix 类型前缀
 | |
|      * @return $this
 | |
|      */
 | |
|     public function setMethodPrefix($method, $prefix = '')
 | |
|     {
 | |
|         if (is_array($method)) {
 | |
|             $this->methodPrefix = array_merge($this->methodPrefix, array_change_key_case($method));
 | |
|         } else {
 | |
|             $this->methodPrefix[strtolower($method)] = $prefix;
 | |
|         }
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 获取请求类型的方法前缀
 | |
|      * @access public
 | |
|      * @param  string    $method 请求类型
 | |
|      * @param  string    $prefix 类型前缀
 | |
|      * @return string|null
 | |
|      */
 | |
|     public function getMethodPrefix($method)
 | |
|     {
 | |
|         $method = strtolower($method);
 | |
| 
 | |
|         return isset($this->methodPrefix[$method]) ? $this->methodPrefix[$method] : null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * rest方法定义和修改
 | |
|      * @access public
 | |
|      * @param  string        $name 方法名称
 | |
|      * @param  array|bool    $resource 资源
 | |
|      * @return $this
 | |
|      */
 | |
|     public function rest($name, $resource = [])
 | |
|     {
 | |
|         if (is_array($name)) {
 | |
|             $this->rest = $resource ? $name : array_merge($this->rest, $name);
 | |
|         } else {
 | |
|             $this->rest[$name] = $resource;
 | |
|         }
 | |
| 
 | |
|         return $this;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 获取rest方法定义的参数
 | |
|      * @access public
 | |
|      * @param  string        $name 方法名称
 | |
|      * @return array|null
 | |
|      */
 | |
|     public function getRest($name = null)
 | |
|     {
 | |
|         if (is_null($name)) {
 | |
|             return $this->rest;
 | |
|         }
 | |
| 
 | |
|         return isset($this->rest[$name]) ? $this->rest[$name] : null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册未匹配路由规则后的处理
 | |
|      * @access public
 | |
|      * @param  string    $route 路由地址
 | |
|      * @param  string    $method 请求类型
 | |
|      * @param  array     $option 路由参数
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function miss($route, $method = '*', array $option = [])
 | |
|     {
 | |
|         return $this->group->addMissRule($route, $method, $option);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 注册一个自动解析的URL路由
 | |
|      * @access public
 | |
|      * @param  string    $route 路由地址
 | |
|      * @return RuleItem
 | |
|      */
 | |
|     public function auto($route)
 | |
|     {
 | |
|         return $this->group->addAutoRule($route);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 检测URL路由
 | |
|      * @access public
 | |
|      * @param  string    $url URL地址
 | |
|      * @param  bool      $must 是否强制路由
 | |
|      * @return Dispatch
 | |
|      * @throws RouteNotFoundException
 | |
|      */
 | |
|     public function check($url, $must = false)
 | |
|     {
 | |
|         // 自动检测域名路由
 | |
|         $domain = $this->checkDomain();
 | |
|         $url    = str_replace($this->config['pathinfo_depr'], '|', $url);
 | |
| 
 | |
|         $completeMatch = $this->config['route_complete_match'];
 | |
| 
 | |
|         $result = $domain->check($this->request, $url, $completeMatch);
 | |
| 
 | |
|         if (false === $result && !empty($this->cross)) {
 | |
|             // 检测跨域路由
 | |
|             $result = $this->cross->check($this->request, $url, $completeMatch);
 | |
|         }
 | |
| 
 | |
|         if (false !== $result) {
 | |
|             // 路由匹配
 | |
|             return $result;
 | |
|         } elseif ($must) {
 | |
|             // 强制路由不匹配则抛出异常
 | |
|             throw new RouteNotFoundException();
 | |
|         }
 | |
| 
 | |
|         // 默认路由解析
 | |
|         return new UrlDispatch($this->request, $this->group, $url, [
 | |
|             'auto_search' => $this->autoSearchController,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 检测域名的路由规则
 | |
|      * @access protected
 | |
|      * @return Domain
 | |
|      */
 | |
|     protected function checkDomain()
 | |
|     {
 | |
|         // 获取当前子域名
 | |
|         $subDomain = $this->request->subDomain();
 | |
| 
 | |
|         $item = false;
 | |
| 
 | |
|         if ($subDomain && count($this->domains) > 1) {
 | |
|             $domain  = explode('.', $subDomain);
 | |
|             $domain2 = array_pop($domain);
 | |
| 
 | |
|             if ($domain) {
 | |
|                 // 存在三级域名
 | |
|                 $domain3 = array_pop($domain);
 | |
|             }
 | |
| 
 | |
|             if ($subDomain && isset($this->domains[$subDomain])) {
 | |
|                 // 子域名配置
 | |
|                 $item = $this->domains[$subDomain];
 | |
|             } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
 | |
|                 // 泛三级域名
 | |
|                 $item      = $this->domains['*.' . $domain2];
 | |
|                 $panDomain = $domain3;
 | |
|             } elseif (isset($this->domains['*']) && !empty($domain2)) {
 | |
|                 // 泛二级域名
 | |
|                 if ('www' != $domain2) {
 | |
|                     $item      = $this->domains['*'];
 | |
|                     $panDomain = $domain2;
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (isset($panDomain)) {
 | |
|                 // 保存当前泛域名
 | |
|                 $this->request->setPanDomain($panDomain);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (false === $item) {
 | |
|             // 检测当前完整域名
 | |
|             $item = $this->domains[$this->host];
 | |
|         }
 | |
| 
 | |
|         if (is_string($item)) {
 | |
|             $item = $this->domains[$item];
 | |
|         }
 | |
| 
 | |
|         return $item;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 清空路由规则
 | |
|      * @access public
 | |
|      * @return void
 | |
|      */
 | |
|     public function clear()
 | |
|     {
 | |
|         $this->app['rule_name']->clear();
 | |
|         $this->group->clear();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * 设置全局的路由分组参数
 | |
|      * @access public
 | |
|      * @param  string    $method     方法名
 | |
|      * @param  array     $args       调用参数
 | |
|      * @return RuleGroup
 | |
|      */
 | |
|     public function __call($method, $args)
 | |
|     {
 | |
|         return call_user_func_array([$this->group, $method], $args);
 | |
|     }
 | |
| 
 | |
|     public function __debugInfo()
 | |
|     {
 | |
|         $data = get_object_vars($this);
 | |
|         unset($data['app'], $data['request']);
 | |
| 
 | |
|         return $data;
 | |
|     }
 | |
| }
 |