Route.php 23 KB

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