0
0

Route.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8. // +----------------------------------------------------------------------
  9. // | Author: liu21st <liu21st@gmail.com>
  10. // +----------------------------------------------------------------------
  11. namespace think;
  12. use think\exception\RouteNotFoundException;
  13. use think\route\AliasRule;
  14. use think\route\Dispatch;
  15. use think\route\dispatch\Url as UrlDispatch;
  16. use think\route\Domain;
  17. use think\route\Resource;
  18. use think\route\Rule;
  19. use think\route\RuleGroup;
  20. use think\route\RuleItem;
  21. class Route
  22. {
  23. /**
  24. * REST定义
  25. * @var array
  26. */
  27. protected $rest = [
  28. 'index' => ['get', '', 'index'],
  29. 'create' => ['get', '/create', 'create'],
  30. 'edit' => ['get', '/<id>/edit', 'edit'],
  31. 'read' => ['get', '/<id>', 'read'],
  32. 'save' => ['post', '', 'save'],
  33. 'update' => ['put', '/<id>', 'update'],
  34. 'delete' => ['delete', '/<id>', 'delete'],
  35. ];
  36. /**
  37. * 请求方法前缀定义
  38. * @var array
  39. */
  40. protected $methodPrefix = [
  41. 'get' => 'get',
  42. 'post' => 'post',
  43. 'put' => 'put',
  44. 'delete' => 'delete',
  45. 'patch' => 'patch',
  46. ];
  47. /**
  48. * 应用对象
  49. * @var App
  50. */
  51. protected $app;
  52. /**
  53. * 请求对象
  54. * @var Request
  55. */
  56. protected $request;
  57. /**
  58. * 当前HOST
  59. * @var string
  60. */
  61. protected $host;
  62. /**
  63. * 当前域名
  64. * @var string
  65. */
  66. protected $domain;
  67. /**
  68. * 当前分组对象
  69. * @var RuleGroup
  70. */
  71. protected $group;
  72. /**
  73. * 配置参数
  74. * @var array
  75. */
  76. protected $config = [];
  77. /**
  78. * 路由绑定
  79. * @var array
  80. */
  81. protected $bind = [];
  82. /**
  83. * 域名对象
  84. * @var array
  85. */
  86. protected $domains = [];
  87. /**
  88. * 跨域路由规则
  89. * @var RuleGroup
  90. */
  91. protected $cross;
  92. /**
  93. * 路由别名
  94. * @var array
  95. */
  96. protected $alias = [];
  97. /**
  98. * 路由是否延迟解析
  99. * @var bool
  100. */
  101. protected $lazy = true;
  102. /**
  103. * 路由是否测试模式
  104. * @var bool
  105. */
  106. protected $isTest;
  107. /**
  108. * (分组)路由规则是否合并解析
  109. * @var bool
  110. */
  111. protected $mergeRuleRegex = true;
  112. /**
  113. * 路由解析自动搜索多级控制器
  114. * @var bool
  115. */
  116. protected $autoSearchController = true;
  117. public function __construct(App $app, array $config = [])
  118. {
  119. $this->app = $app;
  120. $this->request = $app['request'];
  121. $this->config = $config;
  122. $this->host = $this->request->host(true) ?: $config['app_host'];
  123. $this->setDefaultDomain();
  124. }
  125. public function config($name = null)
  126. {
  127. if (is_null($name)) {
  128. return $this->config;
  129. }
  130. return isset($this->config[$name]) ? $this->config[$name] : null;
  131. }
  132. /**
  133. * 配置
  134. * @access public
  135. * @param array $config
  136. * @return void
  137. */
  138. public function setConfig(array $config = [])
  139. {
  140. $this->config = array_merge($this->config, array_change_key_case($config));
  141. }
  142. public static function __make(App $app, Config $config)
  143. {
  144. $config = $config->pull('app');
  145. $route = new static($app, $config);
  146. $route->lazy($config['url_lazy_route'])
  147. ->autoSearchController($config['controller_auto_search'])
  148. ->mergeRuleRegex($config['route_rule_merge']);
  149. return $route;
  150. }
  151. /**
  152. * 设置路由的请求对象实例
  153. * @access public
  154. * @param Request $request 请求对象实例
  155. * @return void
  156. */
  157. public function setRequest($request)
  158. {
  159. $this->request = $request;
  160. }
  161. /**
  162. * 设置路由域名及分组(包括资源路由)是否延迟解析
  163. * @access public
  164. * @param bool $lazy 路由是否延迟解析
  165. * @return $this
  166. */
  167. public function lazy($lazy = true)
  168. {
  169. $this->lazy = $lazy;
  170. return $this;
  171. }
  172. /**
  173. * 设置路由为测试模式
  174. * @access public
  175. * @param bool $test 路由是否测试模式
  176. * @return void
  177. */
  178. public function setTestMode($test)
  179. {
  180. $this->isTest = $test;
  181. }
  182. /**
  183. * 检查路由是否为测试模式
  184. * @access public
  185. * @return bool
  186. */
  187. public function isTest()
  188. {
  189. return $this->isTest;
  190. }
  191. /**
  192. * 设置路由域名及分组(包括资源路由)是否合并解析
  193. * @access public
  194. * @param bool $merge 路由是否合并解析
  195. * @return $this
  196. */
  197. public function mergeRuleRegex($merge = true)
  198. {
  199. $this->mergeRuleRegex = $merge;
  200. $this->group->mergeRuleRegex($merge);
  201. return $this;
  202. }
  203. /**
  204. * 设置路由自动解析是否搜索多级控制器
  205. * @access public
  206. * @param bool $auto 是否自动搜索多级控制器
  207. * @return $this
  208. */
  209. public function autoSearchController($auto = true)
  210. {
  211. $this->autoSearchController = $auto;
  212. return $this;
  213. }
  214. /**
  215. * 初始化默认域名
  216. * @access protected
  217. * @return void
  218. */
  219. protected function setDefaultDomain()
  220. {
  221. // 默认域名
  222. $this->domain = $this->host;
  223. // 注册默认域名
  224. $domain = new Domain($this, $this->host);
  225. $this->domains[$this->host] = $domain;
  226. // 默认分组
  227. $this->group = $domain;
  228. }
  229. /**
  230. * 设置当前域名
  231. * @access public
  232. * @param RuleGroup $group 域名
  233. * @return void
  234. */
  235. public function setGroup(RuleGroup $group)
  236. {
  237. $this->group = $group;
  238. }
  239. /**
  240. * 获取当前分组
  241. * @access public
  242. * @return RuleGroup
  243. */
  244. public function getGroup()
  245. {
  246. return $this->group;
  247. }
  248. /**
  249. * 注册变量规则
  250. * @access public
  251. * @param string|array $name 变量名
  252. * @param string $rule 变量规则
  253. * @return $this
  254. */
  255. public function pattern($name, $rule = '')
  256. {
  257. $this->group->pattern($name, $rule);
  258. return $this;
  259. }
  260. /**
  261. * 注册路由参数
  262. * @access public
  263. * @param string|array $name 参数名
  264. * @param mixed $value 值
  265. * @return $this
  266. */
  267. public function option($name, $value = '')
  268. {
  269. $this->group->option($name, $value);
  270. return $this;
  271. }
  272. /**
  273. * 注册域名路由
  274. * @access public
  275. * @param string|array $name 子域名
  276. * @param mixed $rule 路由规则
  277. * @param array $option 路由参数
  278. * @param array $pattern 变量规则
  279. * @return Domain
  280. */
  281. public function domain($name, $rule = '', $option = [], $pattern = [])
  282. {
  283. // 支持多个域名使用相同路由规则
  284. $domainName = is_array($name) ? array_shift($name) : $name;
  285. if ('*' != $domainName && false === strpos($domainName, '.')) {
  286. $domainName .= '.' . $this->request->rootDomain();
  287. }
  288. if (!isset($this->domains[$domainName])) {
  289. $domain = (new Domain($this, $domainName, $rule, $option, $pattern))
  290. ->lazy($this->lazy)
  291. ->mergeRuleRegex($this->mergeRuleRegex);
  292. $this->domains[$domainName] = $domain;
  293. } else {
  294. $domain = $this->domains[$domainName];
  295. $domain->parseGroupRule($rule);
  296. }
  297. if (is_array($name) && !empty($name)) {
  298. $root = $this->request->rootDomain();
  299. foreach ($name as $item) {
  300. if (false === strpos($item, '.')) {
  301. $item .= '.' . $root;
  302. }
  303. $this->domains[$item] = $domainName;
  304. }
  305. }
  306. // 返回域名对象
  307. return $domain;
  308. }
  309. /**
  310. * 获取域名
  311. * @access public
  312. * @return array
  313. */
  314. public function getDomains()
  315. {
  316. return $this->domains;
  317. }
  318. /**
  319. * 设置路由绑定
  320. * @access public
  321. * @param string $bind 绑定信息
  322. * @param string $domain 域名
  323. * @return $this
  324. */
  325. public function bind($bind, $domain = null)
  326. {
  327. $domain = is_null($domain) ? $this->domain : $domain;
  328. $this->bind[$domain] = $bind;
  329. return $this;
  330. }
  331. /**
  332. * 读取路由绑定
  333. * @access public
  334. * @param string $domain 域名
  335. * @return string|null
  336. */
  337. public function getBind($domain = null)
  338. {
  339. if (is_null($domain)) {
  340. $domain = $this->domain;
  341. } elseif (true === $domain) {
  342. return $this->bind;
  343. } elseif (false === strpos($domain, '.')) {
  344. $domain .= '.' . $this->request->rootDomain();
  345. }
  346. $subDomain = $this->request->subDomain();
  347. if (strpos($subDomain, '.')) {
  348. $name = '*' . strstr($subDomain, '.');
  349. }
  350. if (isset($this->bind[$domain])) {
  351. $result = $this->bind[$domain];
  352. } elseif (isset($name) && isset($this->bind[$name])) {
  353. $result = $this->bind[$name];
  354. } elseif (!empty($subDomain) && isset($this->bind['*'])) {
  355. $result = $this->bind['*'];
  356. } else {
  357. $result = null;
  358. }
  359. return $result;
  360. }
  361. /**
  362. * 读取路由标识
  363. * @access public
  364. * @param string $name 路由标识
  365. * @param string $domain 域名
  366. * @return mixed
  367. */
  368. public function getName($name = null, $domain = null, $method = '*')
  369. {
  370. return $this->app['rule_name']->get($name, $domain, $method);
  371. }
  372. /**
  373. * 读取路由
  374. * @access public
  375. * @param string $rule 路由规则
  376. * @param string $domain 域名
  377. * @return array
  378. */
  379. public function getRule($rule, $domain = null)
  380. {
  381. if (is_null($domain)) {
  382. $domain = $this->domain;
  383. }
  384. return $this->app['rule_name']->getRule($rule, $domain);
  385. }
  386. /**
  387. * 读取路由
  388. * @access public
  389. * @param string $domain 域名
  390. * @return array
  391. */
  392. public function getRuleList($domain = null)
  393. {
  394. return $this->app['rule_name']->getRuleList($domain);
  395. }
  396. /**
  397. * 批量导入路由标识
  398. * @access public
  399. * @param array $name 路由标识
  400. * @return $this
  401. */
  402. public function setName($name)
  403. {
  404. $this->app['rule_name']->import($name);
  405. return $this;
  406. }
  407. /**
  408. * 导入配置文件的路由规则
  409. * @access public
  410. * @param array $rules 路由规则
  411. * @param string $type 请求类型
  412. * @return void
  413. */
  414. public function import(array $rules, $type = '*')
  415. {
  416. // 检查域名部署
  417. if (isset($rules['__domain__'])) {
  418. foreach ($rules['__domain__'] as $key => $rule) {
  419. $this->domain($key, $rule);
  420. }
  421. unset($rules['__domain__']);
  422. }
  423. // 检查变量规则
  424. if (isset($rules['__pattern__'])) {
  425. $this->pattern($rules['__pattern__']);
  426. unset($rules['__pattern__']);
  427. }
  428. // 检查路由别名
  429. if (isset($rules['__alias__'])) {
  430. foreach ($rules['__alias__'] as $key => $val) {
  431. $this->alias($key, $val);
  432. }
  433. unset($rules['__alias__']);
  434. }
  435. // 检查资源路由
  436. if (isset($rules['__rest__'])) {
  437. foreach ($rules['__rest__'] as $key => $rule) {
  438. $this->resource($key, $rule);
  439. }
  440. unset($rules['__rest__']);
  441. }
  442. // 检查路由规则(包含分组)
  443. foreach ($rules as $key => $val) {
  444. if (is_numeric($key)) {
  445. $key = array_shift($val);
  446. }
  447. if (empty($val)) {
  448. continue;
  449. }
  450. if (is_string($key) && 0 === strpos($key, '[')) {
  451. $key = substr($key, 1, -1);
  452. $this->group($key, $val);
  453. } elseif (is_array($val)) {
  454. $this->rule($key, $val[0], $type, $val[1], isset($val[2]) ? $val[2] : []);
  455. } else {
  456. $this->rule($key, $val, $type);
  457. }
  458. }
  459. }
  460. /**
  461. * 注册路由规则
  462. * @access public
  463. * @param string $rule 路由规则
  464. * @param mixed $route 路由地址
  465. * @param string $method 请求类型
  466. * @param array $option 路由参数
  467. * @param array $pattern 变量规则
  468. * @return RuleItem
  469. */
  470. public function rule($rule, $route, $method = '*', array $option = [], array $pattern = [])
  471. {
  472. return $this->group->addRule($rule, $route, $method, $option, $pattern);
  473. }
  474. /**
  475. * 设置跨域有效路由规则
  476. * @access public
  477. * @param Rule $rule 路由规则
  478. * @param string $method 请求类型
  479. * @return $this
  480. */
  481. public function setCrossDomainRule($rule, $method = '*')
  482. {
  483. if (!isset($this->cross)) {
  484. $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
  485. }
  486. $this->cross->addRuleItem($rule, $method);
  487. return $this;
  488. }
  489. /**
  490. * 批量注册路由规则
  491. * @access public
  492. * @param array $rules 路由规则
  493. * @param string $method 请求类型
  494. * @param array $option 路由参数
  495. * @param array $pattern 变量规则
  496. * @return void
  497. */
  498. public function rules($rules, $method = '*', array $option = [], array $pattern = [])
  499. {
  500. $this->group->addRules($rules, $method, $option, $pattern);
  501. }
  502. /**
  503. * 注册路由分组
  504. * @access public
  505. * @param string|array $name 分组名称或者参数
  506. * @param array|\Closure $route 分组路由
  507. * @param array $option 路由参数
  508. * @param array $pattern 变量规则
  509. * @return RuleGroup
  510. */
  511. public function group($name, $route, array $option = [], array $pattern = [])
  512. {
  513. if (is_array($name)) {
  514. $option = $name;
  515. $name = isset($option['name']) ? $option['name'] : '';
  516. }
  517. return (new RuleGroup($this, $this->group, $name, $route, $option, $pattern))
  518. ->lazy($this->lazy)
  519. ->mergeRuleRegex($this->mergeRuleRegex);
  520. }
  521. /**
  522. * 注册路由
  523. * @access public
  524. * @param string $rule 路由规则
  525. * @param mixed $route 路由地址
  526. * @param array $option 路由参数
  527. * @param array $pattern 变量规则
  528. * @return RuleItem
  529. */
  530. public function any($rule, $route = '', array $option = [], array $pattern = [])
  531. {
  532. return $this->rule($rule, $route, '*', $option, $pattern);
  533. }
  534. /**
  535. * 注册GET路由
  536. * @access public
  537. * @param string $rule 路由规则
  538. * @param mixed $route 路由地址
  539. * @param array $option 路由参数
  540. * @param array $pattern 变量规则
  541. * @return RuleItem
  542. */
  543. public function get($rule, $route = '', array $option = [], array $pattern = [])
  544. {
  545. return $this->rule($rule, $route, 'GET', $option, $pattern);
  546. }
  547. /**
  548. * 注册POST路由
  549. * @access public
  550. * @param string $rule 路由规则
  551. * @param mixed $route 路由地址
  552. * @param array $option 路由参数
  553. * @param array $pattern 变量规则
  554. * @return RuleItem
  555. */
  556. public function post($rule, $route = '', array $option = [], array $pattern = [])
  557. {
  558. return $this->rule($rule, $route, 'POST', $option, $pattern);
  559. }
  560. /**
  561. * 注册PUT路由
  562. * @access public
  563. * @param string $rule 路由规则
  564. * @param mixed $route 路由地址
  565. * @param array $option 路由参数
  566. * @param array $pattern 变量规则
  567. * @return RuleItem
  568. */
  569. public function put($rule, $route = '', array $option = [], array $pattern = [])
  570. {
  571. return $this->rule($rule, $route, 'PUT', $option, $pattern);
  572. }
  573. /**
  574. * 注册DELETE路由
  575. * @access public
  576. * @param string $rule 路由规则
  577. * @param mixed $route 路由地址
  578. * @param array $option 路由参数
  579. * @param array $pattern 变量规则
  580. * @return RuleItem
  581. */
  582. public function delete($rule, $route = '', array $option = [], array $pattern = [])
  583. {
  584. return $this->rule($rule, $route, 'DELETE', $option, $pattern);
  585. }
  586. /**
  587. * 注册PATCH路由
  588. * @access public
  589. * @param string $rule 路由规则
  590. * @param mixed $route 路由地址
  591. * @param array $option 路由参数
  592. * @param array $pattern 变量规则
  593. * @return RuleItem
  594. */
  595. public function patch($rule, $route = '', array $option = [], array $pattern = [])
  596. {
  597. return $this->rule($rule, $route, 'PATCH', $option, $pattern);
  598. }
  599. /**
  600. * 注册资源路由
  601. * @access public
  602. * @param string $rule 路由规则
  603. * @param string $route 路由地址
  604. * @param array $option 路由参数
  605. * @param array $pattern 变量规则
  606. * @return Resource
  607. */
  608. public function resource($rule, $route = '', array $option = [], array $pattern = [])
  609. {
  610. return (new Resource($this, $this->group, $rule, $route, $option, $pattern, $this->rest))
  611. ->lazy($this->lazy);
  612. }
  613. /**
  614. * 注册控制器路由 操作方法对应不同的请求前缀
  615. * @access public
  616. * @param string $rule 路由规则
  617. * @param string $route 路由地址
  618. * @param array $option 路由参数
  619. * @param array $pattern 变量规则
  620. * @return RuleGroup
  621. */
  622. public function controller($rule, $route = '', array $option = [], array $pattern = [])
  623. {
  624. $group = new RuleGroup($this, $this->group, $rule, null, $option, $pattern);
  625. foreach ($this->methodPrefix as $type => $val) {
  626. $group->addRule('<action>', $val . '<action>', $type);
  627. }
  628. return $group->prefix($route . '/');
  629. }
  630. /**
  631. * 注册视图路由
  632. * @access public
  633. * @param string|array $rule 路由规则
  634. * @param string $template 路由模板地址
  635. * @param array $vars 模板变量
  636. * @param array $option 路由参数
  637. * @param array $pattern 变量规则
  638. * @return RuleItem
  639. */
  640. public function view($rule, $template = '', array $vars = [], array $option = [], array $pattern = [])
  641. {
  642. return $this->rule($rule, $template, 'GET', $option, $pattern)->view($vars);
  643. }
  644. /**
  645. * 注册重定向路由
  646. * @access public
  647. * @param string|array $rule 路由规则
  648. * @param string $route 路由地址
  649. * @param array $status 状态码
  650. * @param array $option 路由参数
  651. * @param array $pattern 变量规则
  652. * @return RuleItem
  653. */
  654. public function redirect($rule, $route = '', $status = 301, array $option = [], array $pattern = [])
  655. {
  656. return $this->rule($rule, $route, '*', $option, $pattern)->redirect()->status($status);
  657. }
  658. /**
  659. * 注册别名路由
  660. * @access public
  661. * @param string $rule 路由别名
  662. * @param string $route 路由地址
  663. * @param array $option 路由参数
  664. * @return AliasRule
  665. */
  666. public function alias($rule, $route, array $option = [])
  667. {
  668. $aliasRule = new AliasRule($this, $this->group, $rule, $route, $option);
  669. $this->alias[$rule] = $aliasRule;
  670. return $aliasRule;
  671. }
  672. /**
  673. * 获取别名路由定义
  674. * @access public
  675. * @param string $name 路由别名
  676. * @return string|array|null
  677. */
  678. public function getAlias($name = null)
  679. {
  680. if (is_null($name)) {
  681. return $this->alias;
  682. }
  683. return isset($this->alias[$name]) ? $this->alias[$name] : null;
  684. }
  685. /**
  686. * 设置不同请求类型下面的方法前缀
  687. * @access public
  688. * @param string|array $method 请求类型
  689. * @param string $prefix 类型前缀
  690. * @return $this
  691. */
  692. public function setMethodPrefix($method, $prefix = '')
  693. {
  694. if (is_array($method)) {
  695. $this->methodPrefix = array_merge($this->methodPrefix, array_change_key_case($method));
  696. } else {
  697. $this->methodPrefix[strtolower($method)] = $prefix;
  698. }
  699. return $this;
  700. }
  701. /**
  702. * 获取请求类型的方法前缀
  703. * @access public
  704. * @param string $method 请求类型
  705. * @param string $prefix 类型前缀
  706. * @return string|null
  707. */
  708. public function getMethodPrefix($method)
  709. {
  710. $method = strtolower($method);
  711. return isset($this->methodPrefix[$method]) ? $this->methodPrefix[$method] : null;
  712. }
  713. /**
  714. * rest方法定义和修改
  715. * @access public
  716. * @param string $name 方法名称
  717. * @param array|bool $resource 资源
  718. * @return $this
  719. */
  720. public function rest($name, $resource = [])
  721. {
  722. if (is_array($name)) {
  723. $this->rest = $resource ? $name : array_merge($this->rest, $name);
  724. } else {
  725. $this->rest[$name] = $resource;
  726. }
  727. return $this;
  728. }
  729. /**
  730. * 获取rest方法定义的参数
  731. * @access public
  732. * @param string $name 方法名称
  733. * @return array|null
  734. */
  735. public function getRest($name = null)
  736. {
  737. if (is_null($name)) {
  738. return $this->rest;
  739. }
  740. return isset($this->rest[$name]) ? $this->rest[$name] : null;
  741. }
  742. /**
  743. * 注册未匹配路由规则后的处理
  744. * @access public
  745. * @param string $route 路由地址
  746. * @param string $method 请求类型
  747. * @param array $option 路由参数
  748. * @return RuleItem
  749. */
  750. public function miss($route, $method = '*', array $option = [])
  751. {
  752. return $this->group->addMissRule($route, $method, $option);
  753. }
  754. /**
  755. * 注册一个自动解析的URL路由
  756. * @access public
  757. * @param string $route 路由地址
  758. * @return RuleItem
  759. */
  760. public function auto($route)
  761. {
  762. return $this->group->addAutoRule($route);
  763. }
  764. /**
  765. * 检测URL路由
  766. * @access public
  767. * @param string $url URL地址
  768. * @param bool $must 是否强制路由
  769. * @return Dispatch
  770. * @throws RouteNotFoundException
  771. */
  772. public function check($url, $must = false)
  773. {
  774. // 自动检测域名路由
  775. $domain = $this->checkDomain();
  776. $url = str_replace($this->config['pathinfo_depr'], '|', $url);
  777. $completeMatch = $this->config['route_complete_match'];
  778. $result = $domain->check($this->request, $url, $completeMatch);
  779. if (false === $result && !empty($this->cross)) {
  780. // 检测跨域路由
  781. $result = $this->cross->check($this->request, $url, $completeMatch);
  782. }
  783. if (false !== $result) {
  784. // 路由匹配
  785. return $result;
  786. } elseif ($must) {
  787. // 强制路由不匹配则抛出异常
  788. throw new RouteNotFoundException();
  789. }
  790. // 默认路由解析
  791. return new UrlDispatch($this->request, $this->group, $url, [
  792. 'auto_search' => $this->autoSearchController,
  793. ]);
  794. }
  795. /**
  796. * 检测域名的路由规则
  797. * @access protected
  798. * @return Domain
  799. */
  800. protected function checkDomain()
  801. {
  802. // 获取当前子域名
  803. $subDomain = $this->request->subDomain();
  804. $item = false;
  805. if ($subDomain && count($this->domains) > 1) {
  806. $domain = explode('.', $subDomain);
  807. $domain2 = array_pop($domain);
  808. if ($domain) {
  809. // 存在三级域名
  810. $domain3 = array_pop($domain);
  811. }
  812. if ($subDomain && isset($this->domains[$subDomain])) {
  813. // 子域名配置
  814. $item = $this->domains[$subDomain];
  815. } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
  816. // 泛三级域名
  817. $item = $this->domains['*.' . $domain2];
  818. $panDomain = $domain3;
  819. } elseif (isset($this->domains['*']) && !empty($domain2)) {
  820. // 泛二级域名
  821. if ('www' != $domain2) {
  822. $item = $this->domains['*'];
  823. $panDomain = $domain2;
  824. }
  825. }
  826. if (isset($panDomain)) {
  827. // 保存当前泛域名
  828. $this->request->setPanDomain($panDomain);
  829. }
  830. }
  831. if (false === $item) {
  832. // 检测当前完整域名
  833. $item = $this->domains[$this->host];
  834. }
  835. if (is_string($item)) {
  836. $item = $this->domains[$item];
  837. }
  838. return $item;
  839. }
  840. /**
  841. * 清空路由规则
  842. * @access public
  843. * @return void
  844. */
  845. public function clear()
  846. {
  847. $this->app['rule_name']->clear();
  848. $this->group->clear();
  849. }
  850. /**
  851. * 设置全局的路由分组参数
  852. * @access public
  853. * @param string $method 方法名
  854. * @param array $args 调用参数
  855. * @return RuleGroup
  856. */
  857. public function __call($method, $args)
  858. {
  859. return call_user_func_array([$this->group, $method], $args);
  860. }
  861. public function __debugInfo()
  862. {
  863. $data = get_object_vars($this);
  864. unset($data['app'], $data['request']);
  865. return $data;
  866. }
  867. }