Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like Route often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Route, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
31 | class Route |
||
32 | { |
||
33 | /** |
||
34 | * REST定义 |
||
35 | * @var array |
||
36 | */ |
||
37 | protected $rest = [ |
||
38 | 'index' => ['get', '', 'index'], |
||
39 | 'create' => ['get', '/create', 'create'], |
||
40 | 'edit' => ['get', '/<id>/edit', 'edit'], |
||
41 | 'read' => ['get', '/<id>', 'read'], |
||
42 | 'save' => ['post', '', 'save'], |
||
43 | 'update' => ['put', '/<id>', 'update'], |
||
44 | 'delete' => ['delete', '/<id>', 'delete'], |
||
45 | ]; |
||
46 | |||
47 | /** |
||
48 | * 配置参数 |
||
49 | * @var array |
||
50 | */ |
||
51 | protected $config = [ |
||
52 | // pathinfo分隔符 |
||
53 | 'pathinfo_depr' => '/', |
||
54 | // 是否开启路由延迟解析 |
||
55 | 'url_lazy_route' => false, |
||
56 | // 是否强制使用路由 |
||
57 | 'url_route_must' => false, |
||
58 | // 合并路由规则 |
||
59 | 'route_rule_merge' => false, |
||
60 | // 路由是否完全匹配 |
||
61 | 'route_complete_match' => false, |
||
62 | // 去除斜杠 |
||
63 | 'remove_slash' => false, |
||
64 | // 使用注解路由 |
||
65 | 'route_annotation' => false, |
||
66 | // 默认的路由变量规则 |
||
67 | 'default_route_pattern' => '[\w\.]+', |
||
68 | // URL伪静态后缀 |
||
69 | 'url_html_suffix' => 'html', |
||
70 | // 访问控制器层名称 |
||
71 | 'controller_layer' => 'controller', |
||
72 | // 空控制器名 |
||
73 | 'empty_controller' => 'Error', |
||
74 | // 是否使用控制器后缀 |
||
75 | 'controller_suffix' => false, |
||
76 | // 默认控制器名 |
||
77 | 'default_controller' => 'Index', |
||
78 | // 默认操作名 |
||
79 | 'default_action' => 'index', |
||
80 | // 操作方法后缀 |
||
81 | 'action_suffix' => '', |
||
82 | // 非路由变量是否使用普通参数方式(用于URL生成) |
||
83 | 'url_common_param' => true, |
||
84 | ]; |
||
85 | |||
86 | /** |
||
87 | * 当前应用 |
||
88 | * @var App |
||
89 | */ |
||
90 | protected $app; |
||
91 | |||
92 | /** |
||
93 | * 请求对象 |
||
94 | * @var Request |
||
95 | */ |
||
96 | protected $request; |
||
97 | |||
98 | /** |
||
99 | * @var RuleName |
||
100 | */ |
||
101 | protected $ruleName; |
||
102 | |||
103 | /** |
||
104 | * 当前HOST |
||
105 | * @var string |
||
106 | */ |
||
107 | protected $host; |
||
108 | |||
109 | /** |
||
110 | * 当前分组对象 |
||
111 | * @var RuleGroup |
||
112 | */ |
||
113 | protected $group; |
||
114 | |||
115 | /** |
||
116 | * 路由绑定 |
||
117 | * @var array |
||
118 | */ |
||
119 | protected $bind = []; |
||
120 | |||
121 | /** |
||
122 | * 域名对象 |
||
123 | * @var array |
||
124 | */ |
||
125 | protected $domains = []; |
||
126 | |||
127 | /** |
||
128 | * 跨域路由规则 |
||
129 | * @var RuleGroup |
||
130 | */ |
||
131 | protected $cross; |
||
132 | |||
133 | /** |
||
134 | * 路由是否延迟解析 |
||
135 | * @var bool |
||
136 | */ |
||
137 | protected $lazy = false; |
||
138 | |||
139 | /** |
||
140 | * 路由是否测试模式 |
||
141 | * @var bool |
||
142 | */ |
||
143 | protected $isTest = false; |
||
144 | |||
145 | /** |
||
146 | * (分组)路由规则是否合并解析 |
||
147 | * @var bool |
||
148 | */ |
||
149 | protected $mergeRuleRegex = false; |
||
150 | |||
151 | /** |
||
152 | * 是否去除URL最后的斜线 |
||
153 | * @var bool |
||
154 | */ |
||
155 | protected $removeSlash = false; |
||
156 | |||
157 | 18 | public function __construct(App $app) |
|
168 | |||
169 | 18 | protected function init() |
|
183 | |||
184 | 18 | public function config(string $name = null) |
|
192 | |||
193 | /** |
||
194 | * 设置路由域名及分组(包括资源路由)是否延迟解析 |
||
195 | * @access public |
||
196 | * @param bool $lazy 路由是否延迟解析 |
||
197 | * @return $this |
||
198 | */ |
||
199 | 18 | public function lazy(bool $lazy = true) |
|
204 | |||
205 | /** |
||
206 | * 设置路由为测试模式 |
||
207 | * @access public |
||
208 | * @param bool $test 路由是否测试模式 |
||
209 | * @return void |
||
210 | */ |
||
211 | public function setTestMode(bool $test): void |
||
215 | |||
216 | /** |
||
217 | * 检查路由是否为测试模式 |
||
218 | * @access public |
||
219 | * @return bool |
||
220 | */ |
||
221 | 6 | public function isTest(): bool |
|
225 | |||
226 | /** |
||
227 | * 设置路由域名及分组(包括资源路由)是否合并解析 |
||
228 | * @access public |
||
229 | * @param bool $merge 路由是否合并解析 |
||
230 | * @return $this |
||
231 | */ |
||
232 | public function mergeRuleRegex(bool $merge = true) |
||
239 | |||
240 | /** |
||
241 | * 初始化默认域名 |
||
242 | * @access protected |
||
243 | * @return void |
||
244 | */ |
||
245 | 18 | protected function setDefaultDomain(): void |
|
255 | |||
256 | /** |
||
257 | * 设置当前分组 |
||
258 | * @access public |
||
259 | * @param RuleGroup $group 域名 |
||
260 | * @return void |
||
261 | */ |
||
262 | 18 | public function setGroup(RuleGroup $group): void |
|
266 | |||
267 | /** |
||
268 | * 获取指定标识的路由分组 不指定则获取当前分组 |
||
269 | * @access public |
||
270 | * @param string $name 分组标识 |
||
271 | * @return RuleGroup |
||
272 | */ |
||
273 | 18 | public function getGroup(string $name = null) |
|
277 | |||
278 | /** |
||
279 | * 注册变量规则 |
||
280 | * @access public |
||
281 | * @param array $pattern 变量规则 |
||
282 | * @return $this |
||
283 | */ |
||
284 | public function pattern(array $pattern) |
||
290 | |||
291 | /** |
||
292 | * 注册路由参数 |
||
293 | * @access public |
||
294 | * @param array $option 参数 |
||
295 | * @return $this |
||
296 | */ |
||
297 | public function option(array $option) |
||
303 | |||
304 | /** |
||
305 | * 注册域名路由 |
||
306 | * @access public |
||
307 | * @param string|array $name 子域名 |
||
308 | * @param mixed $rule 路由规则 |
||
309 | * @return Domain |
||
310 | */ |
||
311 | public function domain($name, $rule = null): Domain |
||
337 | |||
338 | /** |
||
339 | * 获取域名 |
||
340 | * @access public |
||
341 | * @return array |
||
342 | */ |
||
343 | public function getDomains(): array |
||
347 | |||
348 | /** |
||
349 | * 获取RuleName对象 |
||
350 | * @access public |
||
351 | * @return RuleName |
||
352 | */ |
||
353 | 3 | public function getRuleName(): RuleName |
|
357 | |||
358 | /** |
||
359 | * 设置路由绑定 |
||
360 | * @access public |
||
361 | * @param string $bind 绑定信息 |
||
362 | * @param string $domain 域名 |
||
363 | * @return $this |
||
364 | */ |
||
365 | public function bind(string $bind, string $domain = null) |
||
373 | |||
374 | /** |
||
375 | * 读取路由绑定信息 |
||
376 | * @access public |
||
377 | * @return array |
||
378 | */ |
||
379 | public function getBind(): array |
||
383 | |||
384 | /** |
||
385 | * 读取路由绑定 |
||
386 | * @access public |
||
387 | * @param string $domain 域名 |
||
388 | * @return string|null |
||
389 | */ |
||
390 | 18 | public function getDomainBind(string $domain = null) |
|
418 | |||
419 | /** |
||
420 | * 读取路由标识 |
||
421 | * @access public |
||
422 | * @param string $name 路由标识 |
||
423 | * @param string $domain 域名 |
||
424 | * @param string $method 请求类型 |
||
425 | * @return RuleItem[] |
||
426 | */ |
||
427 | public function getName(string $name = null, string $domain = null, string $method = '*'): array |
||
431 | |||
432 | /** |
||
433 | * 批量导入路由标识 |
||
434 | * @access public |
||
435 | * @param array $name 路由标识 |
||
436 | * @return $this |
||
437 | */ |
||
438 | public function import(array $name): void |
||
442 | |||
443 | /** |
||
444 | * 注册路由标识 |
||
445 | * @access public |
||
446 | * @param string $name 路由标识 |
||
447 | * @param RuleItem $ruleItem 路由规则 |
||
448 | * @param bool $first 是否优先 |
||
449 | * @return void |
||
450 | */ |
||
451 | 12 | public function setName(string $name, RuleItem $ruleItem, bool $first = false): void |
|
455 | |||
456 | /** |
||
457 | * 保存路由规则 |
||
458 | * @access public |
||
459 | * @param string $rule 路由规则 |
||
460 | * @param RuleItem $ruleItem RuleItem对象 |
||
461 | * @return void |
||
462 | */ |
||
463 | 18 | public function setRule(string $rule, RuleItem $ruleItem = null): void |
|
467 | |||
468 | /** |
||
469 | * 读取路由 |
||
470 | * @access public |
||
471 | * @param string $rule 路由规则 |
||
472 | * @return RuleItem[] |
||
473 | */ |
||
474 | 6 | public function getRule(string $rule): array |
|
478 | |||
479 | /** |
||
480 | * 读取路由列表 |
||
481 | * @access public |
||
482 | * @return array |
||
483 | */ |
||
484 | public function getRuleList(): array |
||
488 | |||
489 | /** |
||
490 | * 清空路由规则 |
||
491 | * @access public |
||
492 | * @return void |
||
493 | */ |
||
494 | public function clear(): void |
||
502 | |||
503 | /** |
||
504 | * 注册路由规则 |
||
505 | * @access public |
||
506 | * @param string $rule 路由规则 |
||
507 | * @param mixed $route 路由地址 |
||
508 | * @param string $method 请求类型 |
||
509 | * @return RuleItem |
||
510 | */ |
||
511 | 18 | public function rule(string $rule, $route = null, string $method = '*'): RuleItem |
|
515 | |||
516 | /** |
||
517 | * 设置跨域有效路由规则 |
||
518 | * @access public |
||
519 | * @param Rule $rule 路由规则 |
||
520 | * @param string $method 请求类型 |
||
521 | * @return $this |
||
522 | */ |
||
523 | public function setCrossDomainRule(Rule $rule, string $method = '*') |
||
533 | |||
534 | /** |
||
535 | * 注册路由分组 |
||
536 | * @access public |
||
537 | * @param string|\Closure $name 分组名称或者参数 |
||
538 | * @param mixed $route 分组路由 |
||
539 | * @return RuleGroup |
||
540 | */ |
||
541 | 6 | public function group($name, $route = null): RuleGroup |
|
553 | |||
554 | /** |
||
555 | * 注册路由 |
||
556 | * @access public |
||
557 | * @param string $rule 路由规则 |
||
558 | * @param mixed $route 路由地址 |
||
559 | * @return RuleItem |
||
560 | */ |
||
561 | public function any(string $rule, $route): RuleItem |
||
565 | |||
566 | /** |
||
567 | * 注册GET路由 |
||
568 | * @access public |
||
569 | * @param string $rule 路由规则 |
||
570 | * @param mixed $route 路由地址 |
||
571 | * @return RuleItem |
||
572 | */ |
||
573 | 18 | public function get(string $rule, $route): RuleItem |
|
577 | |||
578 | /** |
||
579 | * 注册POST路由 |
||
580 | * @access public |
||
581 | * @param string $rule 路由规则 |
||
582 | * @param mixed $route 路由地址 |
||
583 | * @return RuleItem |
||
584 | */ |
||
585 | 6 | public function post(string $rule, $route): RuleItem |
|
589 | |||
590 | /** |
||
591 | * 注册PUT路由 |
||
592 | * @access public |
||
593 | * @param string $rule 路由规则 |
||
594 | * @param mixed $route 路由地址 |
||
595 | * @return RuleItem |
||
596 | */ |
||
597 | 6 | public function put(string $rule, $route): RuleItem |
|
601 | |||
602 | /** |
||
603 | * 注册DELETE路由 |
||
604 | * @access public |
||
605 | * @param string $rule 路由规则 |
||
606 | * @param mixed $route 路由地址 |
||
607 | * @return RuleItem |
||
608 | */ |
||
609 | public function delete(string $rule, $route): RuleItem |
||
613 | |||
614 | /** |
||
615 | * 注册PATCH路由 |
||
616 | * @access public |
||
617 | * @param string $rule 路由规则 |
||
618 | * @param mixed $route 路由地址 |
||
619 | * @return RuleItem |
||
620 | */ |
||
621 | public function patch(string $rule, $route): RuleItem |
||
625 | |||
626 | /** |
||
627 | * 注册OPTIONS路由 |
||
628 | * @access public |
||
629 | * @param string $rule 路由规则 |
||
630 | * @param mixed $route 路由地址 |
||
631 | * @return RuleItem |
||
632 | */ |
||
633 | public function options(string $rule, $route): RuleItem |
||
637 | |||
638 | /** |
||
639 | * 注册资源路由 |
||
640 | * @access public |
||
641 | * @param string $rule 路由规则 |
||
642 | * @param string $route 路由地址 |
||
643 | * @return Resource |
||
644 | */ |
||
645 | 3 | public function resource(string $rule, string $route): Resource |
|
650 | |||
651 | /** |
||
652 | * 注册视图路由 |
||
653 | * @access public |
||
654 | * @param string $rule 路由规则 |
||
655 | * @param string $template 路由模板地址 |
||
656 | * @param array $vars 模板变量 |
||
657 | * @return RuleItem |
||
658 | */ |
||
659 | public function view(string $rule, string $template = '', array $vars = []): RuleItem |
||
663 | |||
664 | /** |
||
665 | * 注册重定向路由 |
||
666 | * @access public |
||
667 | * @param string $rule 路由规则 |
||
668 | * @param string $route 路由地址 |
||
669 | * @param int $status 状态码 |
||
670 | * @return RuleItem |
||
671 | */ |
||
672 | public function redirect(string $rule, string $route = '', int $status = 301): RuleItem |
||
676 | |||
677 | /** |
||
678 | * rest方法定义和修改 |
||
679 | * @access public |
||
680 | * @param string|array $name 方法名称 |
||
681 | * @param array|bool $resource 资源 |
||
682 | * @return $this |
||
683 | */ |
||
684 | View Code Duplication | public function rest($name, $resource = []) |
|
694 | |||
695 | /** |
||
696 | * 获取rest方法定义的参数 |
||
697 | * @access public |
||
698 | * @param string $name 方法名称 |
||
699 | * @return array|null |
||
700 | */ |
||
701 | View Code Duplication | public function getRest(string $name = null) |
|
709 | |||
710 | /** |
||
711 | * 注册未匹配路由规则后的处理 |
||
712 | * @access public |
||
713 | * @param string|Closure $route 路由地址 |
||
714 | * @param string $method 请求类型 |
||
715 | * @return RuleItem |
||
716 | */ |
||
717 | public function miss($route, string $method = '*'): RuleItem |
||
721 | |||
722 | /** |
||
723 | * 路由调度 |
||
724 | * @param Request $request |
||
725 | * @param Closure|bool $withRoute |
||
726 | * @return Response |
||
727 | */ |
||
728 | 18 | public function dispatch(Request $request, $withRoute = true) |
|
752 | |||
753 | /** |
||
754 | * 检测URL路由 |
||
755 | * @access public |
||
756 | * @return Dispatch |
||
757 | * @throws RouteNotFoundException |
||
758 | */ |
||
759 | 18 | public function check(): Dispatch |
|
781 | |||
782 | /** |
||
783 | * 获取当前请求URL的pathinfo信息(不含URL后缀) |
||
784 | * @access protected |
||
785 | * @return string |
||
786 | */ |
||
787 | 18 | protected function path(): string |
|
805 | |||
806 | /** |
||
807 | * 默认URL解析 |
||
808 | * @access public |
||
809 | * @param string $url URL地址 |
||
810 | * @return Dispatch |
||
811 | */ |
||
812 | public function url(string $url): UrlDispatch |
||
816 | |||
817 | /** |
||
818 | * 检测域名的路由规则 |
||
819 | * @access protected |
||
820 | * @return Domain |
||
821 | */ |
||
822 | 18 | protected function checkDomain(): Domain |
|
872 | |||
873 | /** |
||
874 | * URL生成 支持路由反射 |
||
875 | * @access public |
||
876 | * @param string $url 路由地址 |
||
877 | * @param array $vars 参数 ['a'=>'val1', 'b'=>'val2'] |
||
878 | * @return UrlBuild |
||
879 | */ |
||
880 | public function buildUrl(string $url = '', array $vars = []): UrlBuild |
||
884 | |||
885 | /** |
||
886 | * 设置全局的路由分组参数 |
||
887 | * @access public |
||
888 | * @param string $method 方法名 |
||
889 | * @param array $args 调用参数 |
||
890 | * @return RuleGroup |
||
891 | */ |
||
892 | public function __call($method, $args) |
||
896 | } |
||
897 |
It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.
We recommend to add an additional type check (or disallow null for the parameter):