Passed
Push — 8.0 ( d13e09...bf2321 )
by liu
13:01
created

Route::path()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0987

Importance

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