Completed
Push — 6.0 ( b8e1f3...5e7dbe )
by liu
04:56
created

Route::options()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
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 <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think;
14
15
use Closure;
16
use think\cache\Driver;
17
use think\exception\HttpResponseException;
18
use think\exception\RouteNotFoundException;
19
use think\route\Dispatch;
20
use think\route\dispatch\Url as UrlDispatch;
21
use think\route\Domain;
22
use think\route\Resource;
23
use think\route\Rule;
24
use think\route\RuleGroup;
25
use think\route\RuleItem;
26
use think\route\RuleName;
27
use think\route\Url as UrlBuild;
28
29
/**
30
 * 路由管理类
31
 */
32
class Route
33
{
34
    /**
35
     * REST定义
36
     * @var array
37
     */
38
    protected $rest = [
39
        'index'  => ['get', '', 'index'],
40
        'create' => ['get', '/create', 'create'],
41
        'edit'   => ['get', '/<id>/edit', 'edit'],
42
        'read'   => ['get', '/<id>', 'read'],
43
        'save'   => ['post', '', 'save'],
44
        'update' => ['put', '/<id>', 'update'],
45
        'delete' => ['delete', '/<id>', 'delete'],
46
    ];
47
48
    /**
49
     * 配置参数
50
     * @var array
51
     */
52
    protected $config = [
53
        // pathinfo分隔符
54
        'pathinfo_depr'         => '/',
55
        // 是否开启路由延迟解析
56
        'url_lazy_route'        => false,
57
        // 是否强制使用路由
58
        'url_route_must'        => false,
59
        // 合并路由规则
60
        'route_rule_merge'      => false,
61
        // 路由是否完全匹配
62
        'route_complete_match'  => false,
63
        // 使用注解路由
64
        'route_annotation'      => false,
65
        // 路由缓存设置
66
        'route_check_cache'     => false,
67
        'route_check_cache_key' => '',
68
        // 是否自动转换URL中的控制器和操作名
69
        'url_convert'           => true,
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 App
93
     */
94
    protected $app;
95
96
    /**
97
     * 请求对象
98
     * @var Request
99
     */
100
    protected $request;
101
102
    /**
103
     * 缓存
104
     * @var Driver
105
     */
106
    protected $cache;
107
108
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
109
     * @var RuleName
110
     */
111
    protected $ruleName;
112
113
    /**
114
     * 当前HOST
115
     * @var string
116
     */
117
    protected $host;
118
119
    /**
120
     * 当前分组对象
121
     * @var RuleGroup
122
     */
123
    protected $group;
124
125
    /**
126
     * 路由绑定
127
     * @var array
128
     */
129
    protected $bind = [];
130
131
    /**
132
     * 域名对象
133
     * @var array
134
     */
135
    protected $domains = [];
136
137
    /**
138
     * 跨域路由规则
139
     * @var RuleGroup
140
     */
141
    protected $cross;
142
143
    /**
144
     * 路由是否延迟解析
145
     * @var bool
146
     */
147
    protected $lazy = true;
148
149
    /**
150
     * 路由是否测试模式
151
     * @var bool
152
     */
153
    protected $isTest = false;
154
155
    /**
156
     * (分组)路由规则是否合并解析
157
     * @var bool
158
     */
159
    protected $mergeRuleRegex = false;
160
161
    public function __construct(App $app)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
162
    {
163
        $this->app      = $app;
164
        $this->ruleName = new RuleName();
165
        $this->setDefaultDomain();
166
    }
167
168
    protected function init()
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function init()
Loading history...
169
    {
170
        $this->config = array_merge($this->config, $this->app->config->get('route'));
171
172
        $this->lazy($this->config['url_lazy_route']);
173
174
        if ($this->config['route_check_cache']) {
175
            $this->cache = $this->app->cache->store(true === $this->config['route_check_cache'] ? '' : $this->config['route_check_cache']);
176
        }
177
178
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
179
            // 读取路由映射文件
180
            $this->import(include $this->app->getRuntimePath() . 'route.php');
181
        }
182
    }
183
184
    public function config(string $name = null)
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function config()
Loading history...
185
    {
186
        if (is_null($name)) {
187
            return $this->config;
188
        }
189
190
        return $this->config[$name] ?? null;
191
    }
192
193
    /**
194
     * 设置路由域名及分组(包括资源路由)是否延迟解析
195
     * @access public
196
     * @param bool $lazy 路由是否延迟解析
197
     * @return $this
198
     */
199
    public function lazy(bool $lazy = true)
200
    {
201
        $this->lazy = $lazy;
202
        return $this;
203
    }
204
205
    /**
206
     * 设置路由为测试模式
207
     * @access public
208
     * @param bool $test 路由是否测试模式
209
     * @return void
210
     */
211
    public function setTestMode(bool $test): void
212
    {
213
        $this->isTest = $test;
214
    }
215
216
    /**
217
     * 检查路由是否为测试模式
218
     * @access public
219
     * @return bool
220
     */
221
    public function isTest(): bool
222
    {
223
        return $this->isTest;
224
    }
225
226
    /**
227
     * 设置路由域名及分组(包括资源路由)是否合并解析
228
     * @access public
229
     * @param bool $merge 路由是否合并解析
230
     * @return $this
231
     */
232
    public function mergeRuleRegex(bool $merge = true)
233
    {
234
        $this->mergeRuleRegex = $merge;
235
        $this->group->mergeRuleRegex($merge);
236
237
        return $this;
238
    }
239
240
    /**
241
     * 初始化默认域名
242
     * @access protected
243
     * @return void
244
     */
245
    protected function setDefaultDomain(): void
246
    {
247
        // 注册默认域名
248
        $domain = new Domain($this);
249
250
        $this->domains['-'] = $domain;
251
252
        // 默认分组
253
        $this->group = $domain;
254
    }
255
256
    /**
257
     * 设置当前分组
258
     * @access public
259
     * @param RuleGroup $group 域名
260
     * @return void
261
     */
262
    public function setGroup(RuleGroup $group): void
263
    {
264
        $this->group = $group;
265
    }
266
267
    /**
0 ignored issues
show
Coding Style introduced by
Parameter $name should have a doc-comment as per coding-style.
Loading history...
268
     * 获取指定标识的路由分组 不指定则获取当前分组
269
     * @access public
270
     * @return RuleGroup
271
     */
272
    public function getGroup(string $name = null)
273
    {
274
        return $name ? $this->ruleName->getGroup($name) : $this->group;
275
    }
276
277
    /**
278
     * 注册变量规则
279
     * @access public
280
     * @param array $pattern 变量规则
281
     * @return $this
282
     */
283
    public function pattern(array $pattern)
284
    {
285
        $this->group->pattern($pattern);
286
287
        return $this;
288
    }
289
290
    /**
291
     * 注册路由参数
292
     * @access public
293
     * @param array $option 参数
294
     * @return $this
295
     */
296
    public function option(array $option)
297
    {
298
        $this->group->option($option);
299
300
        return $this;
301
    }
302
303
    /**
304
     * 注册域名路由
305
     * @access public
306
     * @param string|array $name 子域名
307
     * @param mixed        $rule 路由规则
308
     * @return Domain
309
     */
310
    public function domain($name, $rule = null): Domain
311
    {
312
        // 支持多个域名使用相同路由规则
313
        $domainName = is_array($name) ? array_shift($name) : $name;
314
315
        if (!isset($this->domains[$domainName])) {
316
            $domain = (new Domain($this, $domainName, $rule))
317
                ->lazy($this->lazy)
318
                ->mergeRuleRegex($this->mergeRuleRegex);
319
320
            $this->domains[$domainName] = $domain;
321
        } else {
322
            $domain = $this->domains[$domainName];
323
            $domain->parseGroupRule($rule);
324
        }
325
326
        if (is_array($name) && !empty($name)) {
327
            foreach ($name as $item) {
328
                $this->domains[$item] = $domainName;
329
            }
330
        }
331
332
        // 返回域名对象
333
        return $domain;
334
    }
335
336
    /**
337
     * 获取域名
338
     * @access public
339
     * @return array
340
     */
341
    public function getDomains(): array
342
    {
343
        return $this->domains;
344
    }
345
346
    /**
347
     * 获取RuleName对象
348
     * @access public
349
     * @return RuleName
350
     */
351
    public function getRuleName(): RuleName
352
    {
353
        return $this->ruleName;
354
    }
355
356
    /**
357
     * 设置路由绑定
358
     * @access public
359
     * @param string $bind   绑定信息
360
     * @param string $domain 域名
361
     * @return $this
362
     */
363
    public function bind(string $bind, string $domain = null)
364
    {
365
        $domain = is_null($domain) ? '-' : $domain;
366
367
        $this->bind[$domain] = $bind;
368
369
        return $this;
370
    }
371
372
    /**
373
     * 读取路由绑定信息
374
     * @access public
375
     * @return array
376
     */
377
    public function getBind(): array
378
    {
379
        return $this->bind;
380
    }
381
382
    /**
383
     * 读取路由绑定
384
     * @access public
385
     * @param string $domain 域名
386
     * @return string|null
387
     */
388
    public function getDomainBind(string $domain = null)
389
    {
390
        if (is_null($domain)) {
391
            $domain = $this->host;
392
        } elseif (false === strpos($domain, '.')) {
393
            $domain .= '.' . $this->request->rootDomain();
394
        }
395
396
        $subDomain = $this->request->subDomain();
397
398
        if (strpos($subDomain, '.')) {
399
            $name = '*' . strstr($subDomain, '.');
400
        }
401
402
        if (isset($this->bind[$domain])) {
403
            $result = $this->bind[$domain];
404
        } elseif (isset($name) && isset($this->bind[$name])) {
405
            $result = $this->bind[$name];
406
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
407
            $result = $this->bind['*'];
408
        } else {
409
            $result = null;
410
        }
411
412
        return $result;
413
    }
414
415
    /**
416
     * 读取路由标识
417
     * @access public
418
     * @param string $name   路由标识
419
     * @param string $domain 域名
420
     * @param string $method 请求类型
421
     * @return RuleItem[]
422
     */
423
    public function getName(string $name = null, string $domain = null, string $method = '*'): array
424
    {
425
        return $this->ruleName->getName($name, $domain, $method);
426
    }
427
428
    /**
429
     * 批量导入路由标识
430
     * @access public
431
     * @param array $name 路由标识
432
     * @return $this
433
     */
434
    public function import(array $name): void
435
    {
436
        $this->ruleName->import($name);
437
    }
438
439
    /**
440
     * 注册路由标识
441
     * @access public
442
     * @param string   $name     路由标识
443
     * @param RuleItem $ruleItem 路由规则
444
     * @param bool     $first    是否优先
445
     * @return void
446
     */
447
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
448
    {
449
        $this->ruleName->setName($name, $ruleItem, $first);
450
    }
451
452
    /**
453
     * 保存路由规则
454
     * @access public
455
     * @param string   $rule     路由规则
456
     * @param RuleItem $ruleItem RuleItem对象
457
     * @return void
458
     */
459
    public function setRule(string $rule, RuleItem $ruleItem = null): void
460
    {
461
        $this->ruleName->setRule($rule, $ruleItem);
0 ignored issues
show
Bug introduced by
It seems like $ruleItem can also be of type null; however, parameter $ruleItem of think\route\RuleName::setRule() does only seem to accept think\route\RuleItem, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

461
        $this->ruleName->setRule($rule, /** @scrutinizer ignore-type */ $ruleItem);
Loading history...
462
    }
463
464
    /**
465
     * 读取路由
466
     * @access public
467
     * @param string $rule 路由规则
468
     * @return RuleItem[]
469
     */
470
    public function getRule(string $rule): array
471
    {
472
        return $this->ruleName->getRule($rule);
473
    }
474
475
    /**
476
     * 读取路由列表
477
     * @access public
478
     * @return array
479
     */
480
    public function getRuleList(): array
481
    {
482
        return $this->ruleName->getRuleList();
483
    }
484
485
    /**
486
     * 清空路由规则
487
     * @access public
488
     * @return void
489
     */
490
    public function clear(): void
491
    {
492
        $this->ruleName->clear();
493
494
        if ($this->group) {
495
            $this->group->clear();
496
        }
497
    }
498
499
    /**
500
     * 注册路由规则
501
     * @access public
502
     * @param string $rule   路由规则
503
     * @param mixed  $route  路由地址
504
     * @param string $method 请求类型
505
     * @return RuleItem
506
     */
507
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
508
    {
509
        return $this->group->addRule($rule, $route, $method);
510
    }
511
512
    /**
513
     * 设置跨域有效路由规则
514
     * @access public
515
     * @param Rule   $rule   路由规则
516
     * @param string $method 请求类型
517
     * @return $this
518
     */
519
    public function setCrossDomainRule(Rule $rule, string $method = '*')
520
    {
521
        if (!isset($this->cross)) {
522
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
523
        }
524
525
        $this->cross->addRuleItem($rule, $method);
526
527
        return $this;
528
    }
529
530
    /**
531
     * 注册路由分组
532
     * @access public
533
     * @param string|\Closure $name  分组名称或者参数
534
     * @param mixed           $route 分组路由
535
     * @return RuleGroup
536
     */
537
    public function group($name, $route = null): RuleGroup
538
    {
539
        if ($name instanceof \Closure) {
540
            $route = $name;
541
            $name  = '';
542
        }
543
544
        return (new RuleGroup($this, $this->group, $name, $route))
545
            ->lazy($this->lazy)
546
            ->mergeRuleRegex($this->mergeRuleRegex);
547
    }
548
549
    /**
550
     * 注册路由
551
     * @access public
552
     * @param string $rule  路由规则
553
     * @param mixed  $route 路由地址
554
     * @return RuleItem
555
     */
556
    public function any(string $rule, $route): RuleItem
557
    {
558
        return $this->rule($rule, $route, '*');
559
    }
560
561
    /**
562
     * 注册GET路由
563
     * @access public
564
     * @param string $rule  路由规则
565
     * @param mixed  $route 路由地址
566
     * @return RuleItem
567
     */
568
    public function get(string $rule, $route): RuleItem
569
    {
570
        return $this->rule($rule, $route, 'GET');
571
    }
572
573
    /**
574
     * 注册POST路由
575
     * @access public
576
     * @param string $rule  路由规则
577
     * @param mixed  $route 路由地址
578
     * @return RuleItem
579
     */
580
    public function post(string $rule, $route): RuleItem
581
    {
582
        return $this->rule($rule, $route, 'POST');
583
    }
584
585
    /**
586
     * 注册PUT路由
587
     * @access public
588
     * @param string $rule  路由规则
589
     * @param mixed  $route 路由地址
590
     * @return RuleItem
591
     */
592
    public function put(string $rule, $route): RuleItem
593
    {
594
        return $this->rule($rule, $route, 'PUT');
595
    }
596
597
    /**
598
     * 注册DELETE路由
599
     * @access public
600
     * @param string $rule  路由规则
601
     * @param mixed  $route 路由地址
602
     * @return RuleItem
603
     */
604
    public function delete(string $rule, $route): RuleItem
605
    {
606
        return $this->rule($rule, $route, 'DELETE');
607
    }
608
609
    /**
610
     * 注册PATCH路由
611
     * @access public
612
     * @param string $rule  路由规则
613
     * @param mixed  $route 路由地址
614
     * @return RuleItem
615
     */
616
    public function patch(string $rule, $route): RuleItem
617
    {
618
        return $this->rule($rule, $route, 'PATCH');
619
    }
620
621
    /**
622
     * 注册OPTIONS路由
623
     * @access public
624
     * @param string $rule  路由规则
625
     * @param mixed  $route 路由地址
626
     * @return RuleItem
627
     */
628
    public function options(string $rule, $route): RuleItem
629
    {
630
        return $this->rule($rule, $route, 'OPTIONS');
631
    }
632
633
    /**
634
     * 注册资源路由
635
     * @access public
636
     * @param string $rule  路由规则
637
     * @param string $route 路由地址
638
     * @return Resource
639
     */
640
    public function resource(string $rule, string $route): Resource
641
    {
642
        return (new Resource($this, $this->group, $rule, $route, $this->rest))
643
            ->lazy($this->lazy);
644
    }
645
646
    /**
647
     * 注册视图路由
648
     * @access public
649
     * @param string|array $rule     路由规则
650
     * @param string       $template 路由模板地址
651
     * @param array        $vars     模板变量
652
     * @return RuleItem
653
     */
654
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
655
    {
656
        return $this->rule($rule, $template, 'GET')->view($vars);
657
    }
658
659
    /**
660
     * 注册重定向路由
661
     * @access public
662
     * @param string|array $rule   路由规则
663
     * @param string       $route  路由地址
664
     * @param int          $status 状态码
665
     * @return RuleItem
666
     */
667
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
668
    {
669
        return $this->rule($rule, $route, '*')->redirect()->status($status);
670
    }
671
672
    /**
673
     * rest方法定义和修改
0 ignored issues
show
Coding Style introduced by
Doc comment short description must start with a capital letter
Loading history...
674
     * @access public
675
     * @param string|array $name     方法名称
676
     * @param array|bool   $resource 资源
677
     * @return $this
678
     */
679
    public function rest($name, $resource = [])
680
    {
681
        if (is_array($name)) {
682
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
683
        } else {
684
            $this->rest[$name] = $resource;
685
        }
686
687
        return $this;
688
    }
689
690
    /**
691
     * 获取rest方法定义的参数
692
     * @access public
693
     * @param string $name 方法名称
694
     * @return array|null
695
     */
696
    public function getRest(string $name = null)
697
    {
698
        if (is_null($name)) {
699
            return $this->rest;
700
        }
701
702
        return $this->rest[$name] ?? null;
703
    }
704
705
    /**
706
     * 注册未匹配路由规则后的处理
707
     * @access public
708
     * @param string|Closure $route  路由地址
709
     * @param string         $method 请求类型
710
     * @return RuleItem
711
     */
712
    public function miss($route, string $method = '*'): RuleItem
713
    {
714
        return $this->group->miss($route, $method);
715
    }
716
717
    /**
718
     * 路由调度
719
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
720
     * @param Closure $withRoute
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
721
     * @return Response
722
     */
723
    public function dispatch(Request $request, $withRoute = null)
724
    {
725
        $this->request = $request;
726
        $this->host    = $this->request->host(true);
727
        $this->init();
728
729
        if ($withRoute) {
730
            $checkCallback = function () use ($request, $withRoute) {
0 ignored issues
show
Unused Code introduced by
The import $request is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
731
                //加载路由
732
                $withRoute();
733
                return $this->check();
734
            };
735
736
            if ($this->config['route_check_cache']) {
737
                $dispatch = $this->cache
738
                    ->tag('route_cache')
739
                    ->remember($this->getRouteCacheKey($request), $checkCallback);
740
            } else {
741
                $dispatch = $checkCallback();
742
            }
743
        } else {
744
            $dispatch = $this->url($this->path());
745
        }
746
747
        $dispatch->init($this->app);
748
749
        $this->app->middleware->add(function () use ($dispatch) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
750
            try {
751
                $response = $dispatch->run();
752
            } catch (HttpResponseException $exception) {
753
                $response = $exception->getResponse();
754
            }
755
            return $response;
756
        });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
757
758
        return $this->app->middleware->dispatch($request);
759
    }
760
761
    /**
762
     * 获取路由缓存Key
763
     * @access protected
764
     * @param Request $request
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
765
     * @return string
766
     */
767
    protected function getRouteCacheKey(Request $request): string
768
    {
769
        if (!empty($this->config['route_check_cache_key'])) {
770
            $closure  = $this->config['route_check_cache_key'];
771
            $routeKey = $closure($request);
772
        } else {
773
            $routeKey = md5($request->baseUrl(true) . ':' . $request->method());
774
        }
775
776
        return $routeKey;
777
    }
778
779
    /**
780
     * 检测URL路由
781
     * @access public
782
     * @return Dispatch
783
     * @throws RouteNotFoundException
784
     */
785
    public function check(): Dispatch
786
    {
787
        // 自动检测域名路由
788
        $url = str_replace($this->config['pathinfo_depr'], '|', $this->path());
789
790
        $completeMatch = $this->config['route_complete_match'];
791
792
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
793
794
        if (false === $result && !empty($this->cross)) {
795
            // 检测跨域路由
796
            $result = $this->cross->check($this->request, $url, $completeMatch);
797
        }
798
799
        if (false !== $result) {
800
            return $result;
801
        } elseif ($this->config['url_route_must']) {
802
            throw new RouteNotFoundException();
803
        }
804
805
        return $this->url($url);
806
    }
807
808
    /**
809
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
810
     * @access protected
811
     * @return string
812
     */
813
    protected function path(): string
814
    {
815
        $suffix   = $this->config['url_html_suffix'];
816
        $pathinfo = $this->request->pathinfo();
817
818
        if (false === $suffix) {
819
            // 禁止伪静态访问
820
            $path = $pathinfo;
821
        } elseif ($suffix) {
822
            // 去除正常的URL后缀
823
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
824
        } else {
825
            // 允许任何后缀访问
826
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
827
        }
828
829
        return $path;
830
    }
831
832
    /**
833
     * 默认URL解析
834
     * @access public
835
     * @param string $url URL地址
836
     * @return Dispatch
837
     */
838
    public function url(string $url): UrlDispatch
839
    {
840
        return new UrlDispatch($this->request, $this->group, $url);
841
    }
842
843
    /**
844
     * 检测域名的路由规则
845
     * @access protected
846
     * @return Domain
847
     */
848
    protected function checkDomain(): Domain
849
    {
850
        $item = false;
851
852
        if (count($this->domains) > 1) {
853
            // 获取当前子域名
854
            $subDomain = $this->request->subDomain();
855
856
            $domain  = $subDomain ? explode('.', $subDomain) : [];
857
            $domain2 = $domain ? array_pop($domain) : '';
858
859
            if ($domain) {
860
                // 存在三级域名
861
                $domain3 = array_pop($domain);
862
            }
863
864
            if (isset($this->domains[$this->host])) {
865
                // 子域名配置
866
                $item = $this->domains[$this->host];
867
            } elseif (isset($this->domains[$subDomain])) {
868
                $item = $this->domains[$subDomain];
869
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
870
                // 泛三级域名
871
                $item      = $this->domains['*.' . $domain2];
872
                $panDomain = $domain3;
873
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
874
                // 泛二级域名
875
                if ('www' != $domain2) {
876
                    $item      = $this->domains['*'];
877
                    $panDomain = $domain2;
878
                }
879
            }
880
881
            if (isset($panDomain)) {
882
                // 保存当前泛域名
883
                $this->request->setPanDomain($panDomain);
884
            }
885
        }
886
887
        if (false === $item) {
888
            // 检测全局域名规则
889
            $item = $this->domains['-'];
890
        }
891
892
        if (is_string($item)) {
893
            $item = $this->domains[$item];
894
        }
895
896
        return $item;
897
    }
898
899
    /**
900
     * URL生成 支持路由反射
901
     * @access public
902
     * @param string $url  路由地址
903
     * @param array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
904
     * @return UrlBuild
905
     */
906
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
907
    {
908
        return new UrlBuild($this, $this->app, $url, $vars);
909
    }
910
911
    /**
912
     * 设置全局的路由分组参数
913
     * @access public
914
     * @param string $method 方法名
915
     * @param array  $args   调用参数
916
     * @return RuleGroup
917
     */
918
    public function __call($method, $args)
919
    {
920
        return call_user_func_array([$this->group, $method], $args);
921
    }
922
}
923