Complex classes like Container 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 Container, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
18 | class Container implements ArrayAccess |
||
19 | { |
||
20 | /** |
||
21 | * The current globally available container (if any). |
||
22 | * |
||
23 | * @var static |
||
24 | */ |
||
25 | protected static $instance; |
||
26 | |||
27 | /** |
||
28 | * An array of the types that have been resolved. |
||
29 | * |
||
30 | * @var array |
||
31 | */ |
||
32 | protected $resolved = []; |
||
33 | |||
34 | /** |
||
35 | * The container's bindings. |
||
36 | * |
||
37 | * @var array |
||
38 | */ |
||
39 | protected $bindings = []; |
||
40 | |||
41 | /** |
||
42 | * The container's method bindings. |
||
43 | * |
||
44 | * @var array |
||
45 | */ |
||
46 | protected $methodBindings = []; |
||
47 | |||
48 | /** |
||
49 | * The container's shared instances. |
||
50 | * |
||
51 | * @var array |
||
52 | */ |
||
53 | protected $instances = []; |
||
54 | |||
55 | /** |
||
56 | * The registered type aliases. |
||
57 | * |
||
58 | * @var array |
||
59 | */ |
||
60 | protected $aliases = []; |
||
61 | |||
62 | /** |
||
63 | * The registered aliases keyed by the abstract name. |
||
64 | * |
||
65 | * @var array |
||
66 | */ |
||
67 | protected $abstractAliases = []; |
||
68 | |||
69 | /** |
||
70 | * The extension closures for services. |
||
71 | * |
||
72 | * @var array |
||
73 | */ |
||
74 | protected $extenders = []; |
||
75 | |||
76 | /** |
||
77 | * All of the registered tags. |
||
78 | * |
||
79 | * @var array |
||
80 | */ |
||
81 | protected $tags = []; |
||
82 | |||
83 | /** |
||
84 | * The stack of concretions currently being built. |
||
85 | * |
||
86 | * @var array |
||
87 | */ |
||
88 | protected $buildStack = []; |
||
89 | |||
90 | /** |
||
91 | * The parameter override stack. |
||
92 | * |
||
93 | * @var array |
||
94 | */ |
||
95 | protected $with = []; |
||
96 | |||
97 | /** |
||
98 | * The contextual binding map. |
||
99 | * |
||
100 | * @var array |
||
101 | */ |
||
102 | public $contextual = []; |
||
103 | |||
104 | /** |
||
105 | * All of the registered rebound callbacks. |
||
106 | * |
||
107 | * @var array |
||
108 | */ |
||
109 | protected $reboundCallbacks = []; |
||
110 | |||
111 | /** |
||
112 | * All of the global resolving callbacks. |
||
113 | * |
||
114 | * @var array |
||
115 | */ |
||
116 | protected $globalResolvingCallbacks = []; |
||
117 | |||
118 | /** |
||
119 | * All of the global after resolving callbacks. |
||
120 | * |
||
121 | * @var array |
||
122 | */ |
||
123 | protected $globalAfterResolvingCallbacks = []; |
||
124 | |||
125 | /** |
||
126 | * All of the resolving callbacks by class type. |
||
127 | * |
||
128 | * @var array |
||
129 | */ |
||
130 | protected $resolvingCallbacks = []; |
||
131 | |||
132 | /** |
||
133 | * All of the after resolving callbacks by class type. |
||
134 | * |
||
135 | * @var array |
||
136 | */ |
||
137 | protected $afterResolvingCallbacks = []; |
||
138 | |||
139 | |||
140 | /** |
||
141 | * Determine if the given abstract type has been bound. |
||
142 | * |
||
143 | * @param string $abstract |
||
144 | * @return bool |
||
145 | */ |
||
146 | public function bound($abstract) |
||
152 | |||
153 | /** |
||
154 | * {@inheritdoc} |
||
155 | */ |
||
156 | public function has($id) |
||
160 | |||
161 | /** |
||
162 | * Determine if the given abstract type has been resolved. |
||
163 | * |
||
164 | * @param string $abstract |
||
165 | * @return bool |
||
166 | */ |
||
167 | public function resolved($abstract) |
||
176 | |||
177 | /** |
||
178 | * Determine if a given type is shared. |
||
179 | * |
||
180 | * @param string $abstract |
||
181 | * @return bool |
||
182 | */ |
||
183 | public function isShared($abstract) |
||
189 | |||
190 | /** |
||
191 | * Determine if a given string is an alias. |
||
192 | * |
||
193 | * @param string $name |
||
194 | * @return bool |
||
195 | */ |
||
196 | public function isAlias($name) |
||
200 | |||
201 | /** |
||
202 | * Register a binding with the container. |
||
203 | * |
||
204 | * @param string|array $abstract |
||
205 | * @param \Closure|string|null $concrete |
||
206 | * @param bool $shared |
||
207 | * @return void |
||
208 | */ |
||
209 | public function bind($abstract, $concrete = null, $shared = false) |
||
236 | |||
237 | /** |
||
238 | * Get the Closure to be used when building a type. |
||
239 | * |
||
240 | * @param string $abstract |
||
241 | * @param string $concrete |
||
242 | * @return \Closure |
||
243 | */ |
||
244 | protected function getClosure($abstract, $concrete) |
||
254 | |||
255 | /** |
||
256 | * Determine if the container has a method binding. |
||
257 | * |
||
258 | * @param string $method |
||
259 | * @return bool |
||
260 | */ |
||
261 | public function hasMethodBinding($method) |
||
265 | |||
266 | /** |
||
267 | * Bind a callback to resolve with Container::call. |
||
268 | * |
||
269 | * @param string $method |
||
270 | * @param \Closure $callback |
||
271 | * @return void |
||
272 | */ |
||
273 | public function bindMethod($method, $callback) |
||
277 | |||
278 | /** |
||
279 | * Get the method binding for the given method. |
||
280 | * |
||
281 | * @param string $method |
||
282 | * @param mixed $instance |
||
283 | * @return mixed |
||
284 | */ |
||
285 | public function callMethodBinding($method, $instance) |
||
289 | |||
290 | /** |
||
291 | * Add a contextual binding to the container. |
||
292 | * |
||
293 | * @param string $concrete |
||
294 | * @param string $abstract |
||
295 | * @param \Closure|string $implementation |
||
296 | * @return void |
||
297 | */ |
||
298 | public function addContextualBinding($concrete, $abstract, $implementation) |
||
302 | |||
303 | /** |
||
304 | * Register a binding if it hasn't already been registered. |
||
305 | * |
||
306 | * @param string $abstract |
||
307 | * @param \Closure|string|null $concrete |
||
308 | * @param bool $shared |
||
309 | * @return void |
||
310 | */ |
||
311 | public function bindIf($abstract, $concrete = null, $shared = false) |
||
317 | |||
318 | /** |
||
319 | * Register a shared binding in the container. |
||
320 | * |
||
321 | * @param string|array $abstract |
||
322 | * @param \Closure|string|null $concrete |
||
323 | * @return void |
||
324 | */ |
||
325 | public function singleton($abstract, $concrete = null) |
||
329 | |||
330 | /** |
||
331 | * "Extend" an abstract type in the container. |
||
332 | * |
||
333 | * @param string $abstract |
||
334 | * @param \Closure $closure |
||
335 | * @return void |
||
336 | * @throws \InvalidArgumentException |
||
337 | */ |
||
338 | public function extend($abstract, Closure $closure) |
||
354 | |||
355 | /** |
||
356 | * Register an existing instance as shared in the container. |
||
357 | * |
||
358 | * @param string $abstract |
||
359 | * @param mixed $instance |
||
360 | * @return mixed |
||
361 | */ |
||
362 | public function instance($abstract, $instance) |
||
381 | |||
382 | /** |
||
383 | * Remove an alias from the contextual binding alias cache. |
||
384 | * |
||
385 | * @param string $searched |
||
386 | * @return void |
||
387 | */ |
||
388 | protected function removeAbstractAlias($searched) |
||
402 | |||
403 | /** |
||
404 | * Assign a set of tags to a given binding. |
||
405 | * |
||
406 | * @param array|string $abstracts |
||
407 | * @param array|mixed ...$tags |
||
408 | * @return void |
||
409 | */ |
||
410 | public function tag($abstracts, $tags) |
||
424 | |||
425 | /** |
||
426 | * Resolve all of the bindings for a given tag. |
||
427 | * |
||
428 | * @param string $tag |
||
429 | * @return array |
||
430 | */ |
||
431 | public function tagged($tag) |
||
443 | |||
444 | /** |
||
445 | * Alias a type to a different name. |
||
446 | * |
||
447 | * @param string $abstract |
||
448 | * @param string $alias |
||
449 | * @return void |
||
450 | */ |
||
451 | public function alias($abstract, $alias) |
||
457 | |||
458 | /** |
||
459 | * Bind a new callback to an abstract's rebind event. |
||
460 | * |
||
461 | * @param string $abstract |
||
462 | * @param \Closure $callback |
||
463 | * @return mixed |
||
464 | */ |
||
465 | public function rebinding($abstract, Closure $callback) |
||
473 | |||
474 | /** |
||
475 | * Refresh an instance on the given target and method. |
||
476 | * |
||
477 | * @param string $abstract |
||
478 | * @param mixed $target |
||
479 | * @param string $method |
||
480 | * @return mixed |
||
481 | */ |
||
482 | public function refresh($abstract, $target, $method) |
||
488 | |||
489 | /** |
||
490 | * Fire the "rebound" callbacks for the given abstract type. |
||
491 | * |
||
492 | * @param string $abstract |
||
493 | * @return void |
||
494 | */ |
||
495 | protected function rebound($abstract) |
||
503 | |||
504 | /** |
||
505 | * Get the rebound callbacks for a given type. |
||
506 | * |
||
507 | * @param string $abstract |
||
508 | * @return array |
||
509 | */ |
||
510 | protected function getReboundCallbacks($abstract) |
||
518 | |||
519 | /** |
||
520 | * Get a closure to resolve the given type from the container. |
||
521 | * |
||
522 | * @param string $abstract |
||
523 | * @return \Closure |
||
524 | */ |
||
525 | public function factory($abstract) |
||
531 | |||
532 | /** |
||
533 | * An alias function name for make(). |
||
534 | * |
||
535 | * @param string $abstract |
||
536 | * @param array $parameters |
||
537 | * @return mixed |
||
538 | */ |
||
539 | public function makeWith($abstract, array $parameters = []) |
||
543 | |||
544 | /** |
||
545 | * Resolve the given type from the container. |
||
546 | * |
||
547 | * @param string $abstract |
||
548 | * @param array $parameters |
||
549 | * @return mixed |
||
550 | */ |
||
551 | public function make($abstract, array $parameters = []) |
||
555 | |||
556 | /** |
||
557 | * {@inheritdoc} |
||
558 | */ |
||
559 | public function get($id) |
||
567 | |||
568 | /** |
||
569 | * Resolve the given type from the container. |
||
570 | * |
||
571 | * @param string $abstract |
||
572 | * @param array $parameters |
||
573 | * @return mixed |
||
574 | */ |
||
575 | protected function resolve($abstract, $parameters = []) |
||
628 | |||
629 | /** |
||
630 | * Get the concrete type for a given abstract. |
||
631 | * |
||
632 | * @param string $abstract |
||
633 | * @return mixed $concrete |
||
634 | */ |
||
635 | protected function getConcrete($abstract) |
||
650 | |||
651 | /** |
||
652 | * Get the contextual concrete binding for the given abstract. |
||
653 | * |
||
654 | * @param string $abstract |
||
655 | * @return string|null |
||
656 | */ |
||
657 | protected function getContextualConcrete($abstract) |
||
676 | |||
677 | /** |
||
678 | * Find the concrete binding for the given abstract in the contextual binding array. |
||
679 | * |
||
680 | * @param string $abstract |
||
681 | * @return string|null |
||
682 | */ |
||
683 | protected function findInContextualBindings($abstract) |
||
689 | |||
690 | /** |
||
691 | * Determine if the given concrete is buildable. |
||
692 | * |
||
693 | * @param mixed $concrete |
||
694 | * @param string $abstract |
||
695 | * @return bool |
||
696 | */ |
||
697 | protected function isBuildable($concrete, $abstract) |
||
701 | |||
702 | /** |
||
703 | * Instantiate a concrete instance of the given type. |
||
704 | * |
||
705 | * @param $concrete |
||
706 | * @return mixed|object|void |
||
707 | */ |
||
708 | public function build($concrete) |
||
752 | |||
753 | /** |
||
754 | * Resolve all of the dependencies from the ReflectionParameters. |
||
755 | * |
||
756 | * @param array $dependencies |
||
757 | * @return array |
||
758 | */ |
||
759 | protected function resolveDependencies(array $dependencies) |
||
783 | |||
784 | /** |
||
785 | * Determine if the given dependency has a parameter override. |
||
786 | * |
||
787 | * @param \ReflectionParameter $dependency |
||
788 | * @return bool |
||
789 | */ |
||
790 | protected function hasParameterOverride($dependency) |
||
796 | |||
797 | /** |
||
798 | * Get a parameter override for a dependency. |
||
799 | * |
||
800 | * @param \ReflectionParameter $dependency |
||
801 | * @return mixed |
||
802 | */ |
||
803 | protected function getParameterOverride($dependency) |
||
807 | |||
808 | /** |
||
809 | * Get the last parameter override. |
||
810 | * |
||
811 | * @return array |
||
812 | */ |
||
813 | protected function getLastParameterOverride() |
||
817 | |||
818 | /** |
||
819 | * Resolve a non-class hinted primitive dependency. |
||
820 | * |
||
821 | * @param \ReflectionParameter $parameter |
||
822 | * @return mixed|null|string |
||
823 | */ |
||
824 | protected function resolvePrimitive(ReflectionParameter $parameter) |
||
836 | |||
837 | /** |
||
838 | * Resolve a class based dependency from the container. |
||
839 | * |
||
840 | * @param \ReflectionParameter $parameter |
||
841 | * @return mixed |
||
842 | * @throws \Exception |
||
843 | */ |
||
844 | protected function resolveClass(ReflectionParameter $parameter) |
||
861 | |||
862 | /** |
||
863 | * Throw an exception that the concrete is not instantiable. |
||
864 | * |
||
865 | * @param $concrete |
||
866 | * @throws \Exception |
||
867 | */ |
||
868 | protected function notInstantiable($concrete) |
||
880 | |||
881 | /** |
||
882 | * Throw an exception for an unresolvable primitive. |
||
883 | * |
||
884 | * @param \ReflectionParameter $parameter |
||
885 | * @throws \Exception |
||
886 | */ |
||
887 | protected function unresolvablePrimitive(ReflectionParameter $parameter) |
||
893 | |||
894 | /** |
||
895 | * Register a new resolving callback. |
||
896 | * |
||
897 | * @param string $abstract |
||
898 | * @param \Closure|null $callback |
||
899 | * @return void |
||
900 | */ |
||
901 | public function resolving($abstract, Closure $callback = null) |
||
913 | |||
914 | /** |
||
915 | * Register a new after resolving callback for all types. |
||
916 | * |
||
917 | * @param string $abstract |
||
918 | * @param \Closure|null $callback |
||
919 | * @return void |
||
920 | */ |
||
921 | public function afterResolving($abstract, Closure $callback = null) |
||
933 | |||
934 | /** |
||
935 | * Fire all of the resolving callbacks. |
||
936 | * |
||
937 | * @param string $abstract |
||
938 | * @param mixed $object |
||
939 | * @return void |
||
940 | */ |
||
941 | protected function fireResolvingCallbacks($abstract, $object) |
||
951 | |||
952 | /** |
||
953 | * Fire all of the after resolving callbacks. |
||
954 | * |
||
955 | * @param string $abstract |
||
956 | * @param mixed $object |
||
957 | * @return void |
||
958 | */ |
||
959 | protected function fireAfterResolvingCallbacks($abstract, $object) |
||
967 | |||
968 | /** |
||
969 | * Get all callbacks for a given type. |
||
970 | * |
||
971 | * @param string $abstract |
||
972 | * @param object $object |
||
973 | * @param array $callbacksPerType |
||
974 | * @return array |
||
975 | */ |
||
976 | protected function getCallbacksForType($abstract, $object, array $callbacksPerType) |
||
988 | |||
989 | /** |
||
990 | * Fire an array of callbacks with an object. |
||
991 | * |
||
992 | * @param mixed $object |
||
993 | * @param array $callbacks |
||
994 | * @return void |
||
995 | */ |
||
996 | protected function fireCallbackArray($object, array $callbacks) |
||
1002 | |||
1003 | /** |
||
1004 | * Get the container's bindings. |
||
1005 | * |
||
1006 | * @return array |
||
1007 | */ |
||
1008 | public function getBindings() |
||
1012 | |||
1013 | /** |
||
1014 | * Get the alias for an abstract if available. |
||
1015 | * |
||
1016 | * @param string $abstract |
||
1017 | * @return string |
||
1018 | * @throws \LogicException |
||
1019 | */ |
||
1020 | public function getAlias($abstract) |
||
1032 | |||
1033 | /** |
||
1034 | * Get the extender callbacks for a given type. |
||
1035 | * |
||
1036 | * @param string $abstract |
||
1037 | * @return array |
||
1038 | */ |
||
1039 | protected function getExtenders($abstract) |
||
1049 | |||
1050 | /** |
||
1051 | * Remove all of the extender callbacks for a given type. |
||
1052 | * |
||
1053 | * @param string $abstract |
||
1054 | * @return void |
||
1055 | */ |
||
1056 | public function forgetExtenders($abstract) |
||
1060 | |||
1061 | /** |
||
1062 | * Drop all of the stale instances and aliases. |
||
1063 | * |
||
1064 | * @param string $abstract |
||
1065 | * @return void |
||
1066 | */ |
||
1067 | protected function dropStaleInstances($abstract) |
||
1071 | |||
1072 | /** |
||
1073 | * Remove a resolved instance from the instance cache. |
||
1074 | * |
||
1075 | * @param string $abstract |
||
1076 | * @return void |
||
1077 | */ |
||
1078 | public function forgetInstance($abstract) |
||
1082 | |||
1083 | /** |
||
1084 | * Clear all of the instances from the container. |
||
1085 | * |
||
1086 | * @return void |
||
1087 | */ |
||
1088 | public function forgetInstances() |
||
1092 | |||
1093 | /** |
||
1094 | * Flush the container of all bindings and resolved instances. |
||
1095 | * |
||
1096 | * @return void |
||
1097 | */ |
||
1098 | public function flush() |
||
1106 | |||
1107 | /** |
||
1108 | * Set the globally available instance of the container. |
||
1109 | * |
||
1110 | * @return static |
||
1111 | */ |
||
1112 | public static function getInstance() |
||
1120 | |||
1121 | /** |
||
1122 | * Set the shared instance of the container. |
||
1123 | * |
||
1124 | * @param $container |
||
1125 | * @return static |
||
1126 | */ |
||
1127 | public static function setInstance($container = null) |
||
1131 | |||
1132 | /** |
||
1133 | * Determine if a given offset exists. |
||
1134 | * |
||
1135 | * @param string $key |
||
1136 | * @return bool |
||
1137 | */ |
||
1138 | public function offsetExists($key) |
||
1142 | |||
1143 | /** |
||
1144 | * Get the value at a given offset. |
||
1145 | * |
||
1146 | * @param string $key |
||
1147 | * @return mixed |
||
1148 | */ |
||
1149 | public function offsetGet($key) |
||
1153 | |||
1154 | /** |
||
1155 | * Set the value at a given offset. |
||
1156 | * |
||
1157 | * @param string $key |
||
1158 | * @param mixed $value |
||
1159 | * @return void |
||
1160 | */ |
||
1161 | public function offsetSet($key, $value) |
||
1167 | |||
1168 | /** |
||
1169 | * Unset the value at a given offset. |
||
1170 | * |
||
1171 | * @param string $key |
||
1172 | * @return void |
||
1173 | */ |
||
1174 | public function offsetUnset($key) |
||
1178 | |||
1179 | /** |
||
1180 | * Dynamically access container services. |
||
1181 | * |
||
1182 | * @param string $key |
||
1183 | * @return mixed |
||
1184 | */ |
||
1185 | public function __get($key) |
||
1189 | |||
1190 | /** |
||
1191 | * Dynamically set container services. |
||
1192 | * |
||
1193 | * @param string $key |
||
1194 | * @param mixed $value |
||
1195 | * @return void |
||
1196 | */ |
||
1197 | public function __set($key, $value) |
||
1201 | } |
||
1202 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.