Passed
Push — 8.0 ( ef556c...2d6569 )
by liu
03:04
created

Route::patch()   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~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\Domain;
19
use think\route\Resource;
20
use think\route\ResourceRegister;
21
use think\route\Rule;
22
use think\route\RuleGroup;
23
use think\route\RuleItem;
24
use think\route\RuleName;
25
use think\route\Url as UrlBuild;
26
use think\route\UrlRuleItem;
27
28
/**
29
 * 路由管理类
30
 * @package think
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
        'url_case_sensitive'    => false,
61
        // 合并路由规则
62
        'route_rule_merge'      => false,
63
        // 路由是否完全匹配
64
        'route_complete_match'  => false,
65
        // 去除斜杠
66
        'remove_slash'          => false,
67
        // 使用注解路由
68
        'route_annotation'      => false,
69
        // 默认的路由变量规则
70
        'default_route_pattern' => '[\w\.]+',
71
        // URL伪静态后缀
72
        'url_html_suffix'       => 'html',
73
        // 访问控制器层名称
74
        'controller_layer'      => 'controller',
75
        // 空控制器名
76
        'empty_controller'      => 'Error',
77
        // 是否使用控制器后缀
78
        'controller_suffix'     => false,
79
        // 默认控制器名
80
        'default_controller'    => 'Index',
81
        // 默认操作名
82
        'default_action'        => 'index',
83
        // 操作方法后缀
84
        'action_suffix'         => '',
85
        // 非路由变量是否使用普通参数方式(用于URL生成)
86
        'url_common_param'      => true,
87
    ];
88
89
    /**
90
     * 请求对象
91
     * @var Request
92
     */
93
    protected $request;
94
95
    /**
96
     * @var RuleName
97
     */
98
    protected $ruleName;
99
100
    /**
101
     * 当前HOST
102
     * @var string
103
     */
104
    protected $host;
105
106
    /**
107
     * 当前分组对象
108
     * @var RuleGroup
109
     */
110
    protected $group;
111
112
    /**
113
     * 路由绑定
114
     * @var array
115
     */
116
    protected $bind = [];
117
118
    /**
119
     * 域名对象
120
     * @var Domain[]
121
     */
122
    protected $domains = [];
123
124
    /**
125
     * 跨域路由规则
126
     * @var RuleGroup
127
     */
128
    protected $cross;
129
130
    /**
131
     * 路由是否延迟解析
132
     * @var bool
133
     */
134
    protected $lazy = false;
135
136
    /**
137
     * (分组)路由规则是否合并解析
138
     * @var bool
139
     */
140
    protected $mergeRuleRegex = false;
141
142
    /**
143
     * 是否去除URL最后的斜线
144
     * @var bool
145
     */
146
    protected $removeSlash = false;
147
148 27
    public function __construct(protected App $app)
149
    {
150 27
        $this->ruleName = new RuleName();
151 27
        $this->setDefaultDomain();
152
153 27
        if (is_file($this->app->getRuntimePath() . 'route.php')) {
154
            // 读取路由映射文件
155
            $this->import(include $this->app->getRuntimePath() . 'route.php');
156
        }
157
158 27
        $this->config = array_merge($this->config, $this->app->config->get('route'));
0 ignored issues
show
Bug introduced by
It seems like $this->app->config->get('route') can also be of type null; however, parameter $arrays of array_merge() does only seem to accept array, 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

158
        $this->config = array_merge($this->config, /** @scrutinizer ignore-type */ $this->app->config->get('route'));
Loading history...
159
160 27
        $this->init();
161
    }
162
163 27
    protected function init()
164
    {
165 27
        if (!empty($this->config['middleware'])) {
166
            $this->app->middleware->import($this->config['middleware'], 'route');
167
        }
168
169 27
        $this->lazy($this->config['url_lazy_route']);
170 27
        $this->mergeRuleRegex = $this->config['route_rule_merge'];
171 27
        $this->removeSlash    = $this->config['remove_slash'];
172
173 27
        $this->group->removeSlash($this->removeSlash);
174
175
        // 注册全局MISS路由
176 27
        $this->miss(function () {
177 3
            return Response::create('', 'html', 204)->header(['Allow' => 'GET, POST, PUT, DELETE']);
178 27
        }, 'options');
179
    }
180
181 27
    public function config(?string $name = null)
182
    {
183 27
        if (is_null($name)) {
184
            return $this->config;
185
        }
186
187 27
        return $this->config[$name] ?? null;
188
    }
189
190
    /**
191
     * 设置路由域名及分组(包括资源路由)是否延迟解析
192
     * @access public
193
     * @param bool $lazy 路由是否延迟解析
194
     * @return $this
195
     */
196 27
    public function lazy(bool $lazy = true)
197
    {
198 27
        $this->lazy = $lazy;
199 27
        return $this;
200
    }
201
202
    /**
203
     * 设置路由域名及分组(包括资源路由)是否合并解析
204
     * @access public
205
     * @param bool $merge 路由是否合并解析
206
     * @return $this
207
     */
208
    public function mergeRuleRegex(bool $merge = true)
209
    {
210
        $this->mergeRuleRegex = $merge;
211
        $this->group->mergeRuleRegex($merge);
212
213
        return $this;
214
    }
215
216
    /**
217
     * 初始化默认域名
218
     * @access protected
219
     * @return void
220
     */
221 27
    protected function setDefaultDomain(): void
222
    {
223
        // 注册默认域名
224 27
        $domain = new Domain($this);
225
226 27
        $this->domains['-'] = $domain;
227
228
        // 默认分组
229 27
        $this->group = $domain;
230
    }
231
232
    /**
233
     * 设置当前分组
234
     * @access public
235
     * @param RuleGroup $group 域名
236
     * @return void
237
     */
238 27
    public function setGroup(RuleGroup $group): void
239
    {
240 27
        $this->group = $group;
241
    }
242
243
    /**
244
     * 获取指定标识的路由分组 不指定则获取当前分组
245
     * @access public
246
     * @param string $name 分组标识
247
     * @return RuleGroup
248
     */
249 27
    public function getGroup(?string $name = null)
250
    {
251 27
        return $name ? $this->ruleName->getGroup($name) : $this->group;
252
    }
253
254
    /**
255
     * 注册变量规则
256
     * @access public
257
     * @param array $pattern 变量规则
258
     * @return $this
259
     */
260
    public function pattern(array $pattern)
261
    {
262
        $this->group->pattern($pattern);
263
264
        return $this;
265
    }
266
267
    /**
268
     * 注册路由参数
269
     * @access public
270
     * @param array $option 参数
271
     * @return $this
272
     */
273
    public function option(array $option)
274
    {
275
        $this->group->option($option);
276
277
        return $this;
278
    }
279
280
    /**
281
     * 注册域名路由
282
     * @access public
283
     * @param string|array $name 子域名
284
     * @param mixed        $rule 路由规则
285
     * @return Domain
286
     */
287 3
    public function domain(string | array $name, $rule = null): Domain
288
    {
289
        // 支持多个域名使用相同路由规则
290 3
        $domainName = is_array($name) ? array_shift($name) : $name;
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
291
292 3
        if (!isset($this->domains[$domainName])) {
293 3
            $domain = (new Domain($this, $domainName, $rule, $this->lazy))
294 3
                ->removeSlash($this->removeSlash)
295 3
                ->mergeRuleRegex($this->mergeRuleRegex);
296
297 3
            $this->domains[$domainName] = $domain;
298
        } else {
299
            $domain = $this->domains[$domainName];
300
            $domain->parseGroupRule($rule);
301
        }
302
303 3
        if (is_array($name) && !empty($name)) {
304
            foreach ($name as $item) {
305
                $this->domains[$item] = $domainName;
306
            }
307
        }
308
309
        // 返回域名对象
310 3
        return $domain;
311
    }
312
313
    /**
314
     * 获取域名
315
     * @access public
316
     * @return array
317
     */
318
    public function getDomains(): array
319
    {
320
        return $this->domains;
321
    }
322
323
    /**
324
     * 获取RuleName对象
325
     * @access public
326
     * @return RuleName
327
     */
328
    public function getRuleName(): RuleName
329
    {
330
        return $this->ruleName;
331
    }
332
333
    /**
334
     * 设置路由绑定
335
     * @access public
336
     * @param string $bind   绑定信息
337
     * @param string $domain 域名
338
     * @return $this
339
     */
340
    public function bind(string $bind, ?string $domain = null)
341
    {
342
        $domain = is_null($domain) ? '-' : $domain;
343
344
        $this->bind[$domain] = $bind;
345
346
        return $this;
347
    }
348
349
    /**
350
     * 读取路由绑定信息
351
     * @access public
352
     * @return array
353
     */
354
    public function getBind(): array
355
    {
356
        return $this->bind;
357
    }
358
359
    /**
360
     * 读取路由绑定
361
     * @access public
362
     * @param string $domain 域名
363
     * @return string|null
364
     */
365 27
    public function getDomainBind(?string $domain = null)
366
    {
367 27
        if (is_null($domain)) {
368 24
            $domain = $this->host;
369 3
        } elseif (!str_contains($domain, '.') && $this->request) {
370 3
            $domain .= '.' . $this->request->rootDomain();
371
        }
372
373 27
        if ($this->request) {
374 27
            $subDomain = $this->request->subDomain();
375
376 27
            if (str_contains($subDomain, '.')) {
377
                $name = '*' . strstr($subDomain, '.');
378
            }
379
        }
380
381 27
        if (isset($this->bind[$domain])) {
382
            $result = $this->bind[$domain];
383 27
        } elseif (isset($name) && isset($this->bind[$name])) {
384
            $result = $this->bind[$name];
385 27
        } elseif (!empty($subDomain) && isset($this->bind['*'])) {
386
            $result = $this->bind['*'];
387
        } else {
388 27
            $result = null;
389
        }
390
391 27
        return $result;
392
    }
393
394
    /**
395
     * 读取路由标识
396
     * @access public
397
     * @param string $name   路由标识
398
     * @param string $domain 域名
399
     * @param string $method 请求类型
400
     * @return array
401
     */
402
    public function getName(?string $name = null, ?string $domain = null, string $method = '*'): array
403
    {
404
        return $this->ruleName->getName($name, $domain, $method);
405
    }
406
407
    /**
408
     * 批量导入路由标识
409
     * @access public
410
     * @param array $name 路由标识
411
     * @return void
412
     */
413
    public function import(array $name): void
414
    {
415
        $this->ruleName->import($name);
416
    }
417
418
    /**
419
     * 注册路由标识
420
     * @access public
421
     * @param string   $name     路由标识
422
     * @param RuleItem $ruleItem 路由规则
423
     * @param bool     $first    是否优先
424
     * @return void
425
     */
426 12
    public function setName(string $name, RuleItem $ruleItem, bool $first = false): void
427
    {
428 12
        $this->ruleName->setName($name, $ruleItem, $first);
429
    }
430
431
    /**
432
     * 保存路由规则
433
     * @access public
434
     * @param string   $rule     路由规则
435
     * @param RuleItem $ruleItem RuleItem对象
436
     * @return void
437
     */
438 27
    public function setRule(string $rule, ?RuleItem $ruleItem = null): void
439
    {
440 27
        $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

440
        $this->ruleName->setRule($rule, /** @scrutinizer ignore-type */ $ruleItem);
Loading history...
441
    }
442
443
    /**
444
     * 读取路由
445
     * @access public
446
     * @param string $rule 路由规则
447
     * @return RuleItem[]
448
     */
449
    public function getRule(string $rule): array
450
    {
451
        return $this->ruleName->getRule($rule);
452
    }
453
454
    /**
455
     * 读取路由列表
456
     * @access public
457
     * @return array
458
     */
459
    public function getRuleList(): array
460
    {
461
        return $this->ruleName->getRuleList();
462
    }
463
464
    /**
465
     * 清空路由规则
466
     * @access public
467
     * @return void
468
     */
469
    public function clear(): void
470
    {
471
        $this->ruleName->clear();
472
473
        if ($this->group) {
474
            $this->group->clear();
475
        }
476
    }
477
478
    /**
479
     * 注册路由规则
480
     * @access public
481
     * @param string $rule   路由规则
482
     * @param mixed  $route  路由地址
483
     * @param string $method 请求类型
484
     * @return RuleItem
485
     */
486 24
    public function rule(string $rule, $route = null, string $method = '*'): RuleItem
487
    {
488 24
        return $this->group->addRule($rule, $route, $method);
489
    }
490
491
    /**
492
     * 设置路由规则全局有效
493
     * @access public
494
     * @param Rule   $rule   路由规则
495
     * @return $this
496
     */
497
    public function setCrossDomainRule(Rule $rule)
498
    {
499
        if (!isset($this->cross)) {
500
            $this->cross = (new RuleGroup($this))->mergeRuleRegex($this->mergeRuleRegex);
501
        }
502
503
        $this->cross->addRuleItem($rule);
504
505
        return $this;
506
    }
507
508
    /**
509
     * 注册路由分组
510
     * @access public
511
     * @param string|Closure $name  分组名称或者参数
512
     * @param mixed           $route 分组路由
513
     * @return RuleGroup
514
     */
515 3
    public function group(string | Closure $name, $route = null): RuleGroup
516
    {
517 3
        if ($name instanceof Closure) {
518 3
            $route = $name;
519 3
            $name  = '';
520
        }
521
522 3
        return (new RuleGroup($this, $this->group, $name, $route, $this->lazy))
523 3
            ->removeSlash($this->removeSlash)
524 3
            ->mergeRuleRegex($this->mergeRuleRegex);
525
    }
526
527
    /**
528
     * 注册路由
529
     * @access public
530
     * @param string $rule  路由规则
531
     * @param mixed  $route 路由地址
532
     * @return RuleItem
533
     */
534
    public function any(string $rule, $route): RuleItem
535
    {
536
        return $this->rule($rule, $route, '*');
537
    }
538
539
    /**
540
     * 注册GET路由
541
     * @access public
542
     * @param string $rule  路由规则
543
     * @param mixed  $route 路由地址
544
     * @return RuleItem
545
     */
546 18
    public function get(string $rule, $route): RuleItem
547
    {
548 18
        return $this->rule($rule, $route, 'GET');
549
    }
550
551
    /**
552
     * 注册POST路由
553
     * @access public
554
     * @param string $rule  路由规则
555
     * @param mixed  $route 路由地址
556
     * @return RuleItem
557
     */
558 3
    public function post(string $rule, $route): RuleItem
559
    {
560 3
        return $this->rule($rule, $route, 'POST');
561
    }
562
563
    /**
564
     * 注册PUT路由
565
     * @access public
566
     * @param string $rule  路由规则
567
     * @param mixed  $route 路由地址
568
     * @return RuleItem
569
     */
570 3
    public function put(string $rule, $route): RuleItem
571
    {
572 3
        return $this->rule($rule, $route, 'PUT');
573
    }
574
575
    /**
576
     * 注册DELETE路由
577
     * @access public
578
     * @param string $rule  路由规则
579
     * @param mixed  $route 路由地址
580
     * @return RuleItem
581
     */
582
    public function delete(string $rule, $route): RuleItem
583
    {
584
        return $this->rule($rule, $route, 'DELETE');
585
    }
586
587
    /**
588
     * 注册PATCH路由
589
     * @access public
590
     * @param string $rule  路由规则
591
     * @param mixed  $route 路由地址
592
     * @return RuleItem
593
     */
594
    public function patch(string $rule, $route): RuleItem
595
    {
596
        return $this->rule($rule, $route, 'PATCH');
597
    }
598
599
    /**
600
     * 注册HEAD路由
601
     * @access public
602
     * @param string $rule  路由规则
603
     * @param mixed  $route 路由地址
604
     * @return RuleItem
605
     */
606
    public function head(string $rule, $route): RuleItem
607
    {
608
        return $this->rule($rule, $route, 'HEAD');
609
    }
610
611
    /**
612
     * 注册OPTIONS路由
613
     * @access public
614
     * @param string $rule  路由规则
615
     * @param mixed  $route 路由地址
616
     * @return RuleItem
617
     */
618
    public function options(string $rule, $route): RuleItem
619
    {
620
        return $this->rule($rule, $route, 'OPTIONS');
621
    }
622
623
    /**
624
     * 注册资源路由
625
     * @access public
626
     * @param string $rule  路由规则
627
     * @param string $route 路由地址
628
     * @return Resource|ResourceRegister
629
     */
630
    public function resource(string $rule, string $route)
631
    {
632
        $resource = new Resource($this, $this->group, $rule, $route, $this->rest);
633
634
        if (!$this->lazy) {
635
            return new ResourceRegister($resource);
636
        }
637
638
        return $resource;
639
    }
640
641
    /**
642
     * 注册视图路由
643
     * @access public
644
     * @param string $rule     路由规则
645
     * @param string $template 路由模板地址
646
     * @param array  $vars     模板变量
647
     * @return RuleItem
648
     */
649 3
    public function view(string $rule, string $template = '', array $vars = []): RuleItem
650
    {
651 3
        return $this->rule($rule, function () use ($vars, $template) {
652 3
            return Response::create($template, 'view')->assign($vars);
0 ignored issues
show
Bug introduced by
The method assign() does not exist on think\Response. It seems like you code against a sub-type of think\Response such as think\response\View. ( Ignorable by Annotation )

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

652
            return Response::create($template, 'view')->/** @scrutinizer ignore-call */ assign($vars);
Loading history...
653 3
        }, 'GET');
654
    }
655
656
    /**
657
     * 注册重定向路由
658
     * @access public
659
     * @param string $rule   路由规则
660
     * @param string $route  路由地址
661
     * @param int    $status 状态码
662
     * @return RuleItem
663
     */
664 3
    public function redirect(string $rule, string $route = '', int $status = 301): RuleItem
665
    {
666 3
        return $this->rule($rule, function (Request $request) use ($status, $route) {
667 3
            $search  = $replace  = [];
668 3
            $matches = $request->rule()->getVars();
669
670 3
            foreach ($matches as $key => $value) {
671
                $search[]  = '<' . $key . '>';
672
                $replace[] = $value;
673
674
                $search[]  = ':' . $key;
675
                $replace[] = $value;
676
            }
677
678 3
            $route = str_replace($search, $replace, $route);
679 3
            return Response::create($route, 'redirect')->code($status);
680 3
        }, '*');
681
    }
682
683
    /**
684
     * rest方法定义和修改
685
     * @access public
686
     * @param string|array $name     方法名称
687
     * @param array|bool   $resource 资源
688
     * @return $this
689
     */
690
    public function rest(string | array $name, array | bool $resource = [])
691
    {
692
        if (is_array($name)) {
0 ignored issues
show
introduced by
The condition is_array($name) is always true.
Loading history...
693
            $this->rest = $resource ? $name : array_merge($this->rest, $name);
694
        } else {
695
            $this->rest[$name] = $resource;
696
        }
697
698
        return $this;
699
    }
700
701
    /**
702
     * 获取rest方法定义的参数
703
     * @access public
704
     * @param string $name 方法名称
705
     * @return array|null
706
     */
707
    public function getRest(?string $name = null)
708
    {
709
        if (is_null($name)) {
710
            return $this->rest;
711
        }
712
713
        return $this->rest[$name] ?? null;
714
    }
715
716
    /**
717
     * 注册未匹配路由规则后的处理
718
     * @access public
719
     * @param string|Closure $route  路由地址
720
     * @param string         $method 请求类型
721
     * @return RuleItem
722
     */
723 27
    public function miss(string | Closure $route, string $method = '*'): RuleItem
724
    {
725 27
        return $this->group->miss($route, $method);
726
    }
727
728
    /**
729
     * 路由调度
730
     * @param Request $request
731
     * @param Closure|bool $withRoute
732
     * @return Response
733
     */
734 27
    public function dispatch(Request $request, Closure | bool $withRoute = true)
735
    {
736 27
        $this->request = $request;
737 27
        $this->host    = $this->request->host(true);
738 27
        $completeMatch = (bool) $this->config['route_complete_match'];
739
740 27
        if ($withRoute) {
741
            //加载路由
742 27
            if ($withRoute instanceof Closure) {
743
                $withRoute();
744
            }
745 27
            $dispatch = $this->check($completeMatch);
746
        } else {
747
            $dispatch = $this->url()->check($this->request, $this->path(), $completeMatch);
748
        }
749
750 27
        $dispatch->init($this->app);
751
752 27
        return $this->app->middleware->pipeline('route')
753 27
            ->send($request)
754 27
            ->then(function () use ($dispatch) {
755 27
                return $dispatch->run();
756 27
            });
757
    }
758
759
    /**
760
     * 检测URL路由
761
     * @access public
762
     * @param  bool $completeMatch
763
     * @return Dispatch|false
764
     * @throws RouteNotFoundException
765
     */
766 27
    public function check(bool $completeMatch = false)
767
    {
768
        // 自动检测域名路由
769 27
        $url = str_replace($this->config['pathinfo_depr'], '|', $this->path());
770
771 27
        $result = $this->checkDomain()->check($this->request, $url, $completeMatch);
772
773 27
        if (false === $result && !empty($this->cross)) {
774
            // 检测跨域路由
775
            $result = $this->cross->check($this->request, $url, $completeMatch);
776
        }
777
778 27
        if (false !== $result) {
779 24
            return $result;
780 3
        } elseif ($this->config['url_route_must']) {
781
            throw new RouteNotFoundException();
782
        }
783 3
        return $this->url()->check($this->request, $url, $completeMatch);
784
    }
785
786
    /**
787
     * 获取当前请求URL的pathinfo信息(不含URL后缀)
788
     * @access protected
789
     * @return string
790
     */
791 27
    protected function path(): string
792
    {
793 27
        $suffix   = $this->config['url_html_suffix'];
794 27
        $pathinfo = $this->request->pathinfo();
795
796 27
        if (false === $suffix) {
797
            // 禁止伪静态访问
798
            $path = $pathinfo;
799 27
        } elseif ($suffix) {
800
            // 去除正常的URL后缀
801 27
            $path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo);
802
        } else {
803
            // 允许任何后缀访问
804
            $path = preg_replace('/\.' . $this->request->ext() . '$/i', '', $pathinfo);
805
        }
806
807 27
        return $path;
808
    }
809
810
    /**
811
     * 自动多模块路由解析
812
     * @access public
813
     * @param  string $default 默认模块
814
     * @return RuleItem
815
     */
816
    public function autoMultiModule(string $default = '')
817
    {
818
        $this->group(':module')->pattern([
819
            'module' => '[A-Za-z0-9\.\_]+',
820
        ])->useUrlDispatch($this->config['default_route']);
821
822
        if ($default) {
823
            $this->get('/', $default . '/' . $this->config['default_controller'] . '/' . $this->config['default_action']);
824
        }
825
    }
826
827
    /**
828
     * 注册默认URL解析路由
829
     * @access public
830
     * @param  RuleGroup $group 解析规则
831
     * @param  array     $option 解析规则
832
     * @return RuleItem
833
     */
834 3
    public function url(?RuleGroup $group = null, array $option = []): RuleItem
835
    {
836 3
        if (!empty($option)) {
837
            [$rule, $route] = $option;
838
        } else {
839 3
            $group = $group ?: $this->group;
840 3
            $name  = $group->getfullName();
841 3
            $layer = $name ? $name . '/' : '';
842 3
            $rule  = $layer . '[:controller]/[:action]';
843 3
            $route = $layer . ':controller/:action';
844
        }
845
846 3
        $ruleItem = new UrlRuleItem($this, new RuleGroup($this), '_default_route_', $rule, $route, '*');
847
848 3
        return $ruleItem->default([
849 3
            'controller' => $this->config['default_controller'],
850 3
            'action'     => $this->config['default_action'],
851 3
        ])->pattern([
852 3
            'controller' => '[A-Za-z0-9\.\_]+',
853 3
            'action'     => '[A-Za-z0-9\_]+',
854 3
        ]);
855
    }
856
857
    /**
858
     * 检测域名的路由规则
859
     * @access protected
860
     * @return Domain
861
     */
862 27
    protected function checkDomain(): Domain
863
    {
864 27
        $item = false;
865
866 27
        if (count($this->domains) > 1) {
867
            // 获取当前子域名
868 3
            $subDomain = $this->request->subDomain();
869
870 3
            $domain  = $subDomain ? explode('.', $subDomain) : [];
871 3
            $domain2 = $domain ? array_pop($domain) : '';
872
873 3
            if ($domain) {
874
                // 存在三级域名
875
                $domain3 = array_pop($domain);
876
            }
877
878 3
            if (isset($this->domains[$this->host])) {
879
                // 子域名配置
880
                $item = $this->domains[$this->host];
881 3
            } elseif (isset($this->domains[$subDomain])) {
882 3
                $item = $this->domains[$subDomain];
883
            } elseif (isset($this->domains['*.' . $domain2]) && !empty($domain3)) {
884
                // 泛三级域名
885
                $item      = $this->domains['*.' . $domain2];
886
                $panDomain = $domain3;
887
            } elseif (isset($this->domains['*']) && !empty($domain2)) {
888
                // 泛二级域名
889
                if ('www' != $domain2) {
890
                    $item      = $this->domains['*'];
891
                    $panDomain = $domain2;
892
                }
893
            }
894
895 3
            if (isset($panDomain)) {
896
                // 保存当前泛域名
897
                $this->request->setPanDomain($panDomain);
898
            }
899
        }
900
901 27
        if (false === $item) {
902
            // 检测全局域名规则
903 24
            $item = $this->domains['-'];
904
        }
905
906 27
        if (is_string($item)) {
907
            $item = $this->domains[$item];
908
        }
909
910 27
        return $item;
911
    }
912
913
    /**
914
     * URL生成 支持路由反射
915
     * @access public
916
     * @param string $url  路由地址
917
     * @param array  $vars 参数 ['a'=>'val1', 'b'=>'val2']
918
     * @return UrlBuild
919
     */
920
    public function buildUrl(string $url = '', array $vars = []): UrlBuild
921
    {
922
        return $this->app->make(UrlBuild::class, [$this, $this->app, $url, $vars], true);
923
    }
924
925
    /**
926
     * 设置全局的路由分组参数
927
     * @access public
928
     * @param string $method 方法名
929
     * @param array  $args   调用参数
930
     * @return RuleGroup
931
     */
932
    public function __call($method, $args)
933
    {
934
        return call_user_func_array([$this->group, $method], $args);
935
    }
936
}
937