Complex classes like QueryString 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 QueryString, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | final class QueryString |
||
10 | { |
||
11 | /** |
||
12 | * @var array |
||
13 | */ |
||
14 | private $params = []; |
||
15 | |||
16 | /** |
||
17 | * @var QueryStringRendererInterface |
||
18 | */ |
||
19 | private $renderer; |
||
20 | |||
21 | /** |
||
22 | * @var QueryStringRendererInterface |
||
23 | */ |
||
24 | private static $defaultRenderer; |
||
25 | |||
26 | /** |
||
27 | * QueryString constructor. |
||
28 | * @param array|null $params |
||
29 | * @param QueryStringRendererInterface|null $renderer |
||
30 | * @throws \InvalidArgumentException |
||
31 | */ |
||
32 | protected function __construct(?array $params = [], QueryStringRendererInterface $renderer = null) |
||
40 | |||
41 | /** |
||
42 | * @param array $params |
||
43 | * @param QueryStringRendererInterface|null $renderer |
||
44 | * @return QueryString |
||
45 | */ |
||
46 | private static function createFromParams(array $params, QueryStringRendererInterface $renderer = null): self |
||
50 | |||
51 | /** |
||
52 | * @param \Psr\Http\Message\UriInterface $uri |
||
53 | * @param QueryStringRendererInterface|null $renderer |
||
54 | * @return QueryString |
||
55 | * @throws \TypeError |
||
56 | */ |
||
57 | private static function createFromUri($uri, QueryStringRendererInterface $renderer = null): self |
||
64 | |||
65 | /** |
||
66 | * @param string $qs |
||
67 | * @param QueryStringRendererInterface|null $renderer |
||
68 | * @return QueryString |
||
69 | */ |
||
70 | private static function createFromString(string $qs, QueryStringRendererInterface $renderer = null): self |
||
76 | |||
77 | /** |
||
78 | * @param QueryStringRendererInterface|null $renderer |
||
79 | * @return QueryString |
||
80 | * @throws \RuntimeException |
||
81 | */ |
||
82 | public static function createFromCurrentLocation(QueryStringRendererInterface $renderer = null): self |
||
89 | |||
90 | /** |
||
91 | * @return QueryString |
||
92 | * @throws \RuntimeException |
||
93 | */ |
||
94 | public function withCurrentLocation(): self |
||
98 | |||
99 | /** |
||
100 | * @param $input |
||
101 | * @return QueryString |
||
102 | * @throws \InvalidArgumentException |
||
103 | */ |
||
104 | public static function factory($input = null, QueryStringRendererInterface $renderer = null): self |
||
117 | |||
118 | /** |
||
119 | * @return array |
||
120 | */ |
||
121 | public function getParams(): ?array |
||
125 | |||
126 | /** |
||
127 | * @param string $key |
||
128 | * @param array ...$deepKeys |
||
129 | * @return mixed|null |
||
130 | */ |
||
131 | public function getParam(string $key, ...$deepKeys) |
||
142 | |||
143 | /** |
||
144 | * @param string $key |
||
145 | * @return bool |
||
146 | */ |
||
147 | public function hasParam(string $key, ...$deepKeys): bool |
||
151 | |||
152 | /** |
||
153 | * Yield key => value pairs. |
||
154 | * |
||
155 | * @return Generator |
||
156 | */ |
||
157 | public function getPairs(): Generator |
||
165 | |||
166 | /** |
||
167 | * @param string $key |
||
168 | * @param $value |
||
169 | * @return QueryString |
||
170 | */ |
||
171 | public function withParam(string $key, $value): self |
||
177 | |||
178 | /** |
||
179 | * @param array $params |
||
180 | * @return QueryString |
||
181 | */ |
||
182 | public function withParams(array $params): self |
||
191 | |||
192 | /** |
||
193 | * @param string $key |
||
194 | * @param array ...$deepKeys |
||
195 | * @return QueryString |
||
196 | */ |
||
197 | public function withoutParam(string $key, ...$deepKeys): self |
||
216 | |||
217 | /** |
||
218 | * @return QueryStringRendererInterface |
||
219 | */ |
||
220 | public function getRenderer(): QueryStringRendererInterface |
||
224 | |||
225 | /** |
||
226 | * @param QueryStringRendererInterface $renderer |
||
227 | * @return QueryString |
||
228 | */ |
||
229 | public function withRenderer(QueryStringRendererInterface $renderer): self |
||
235 | |||
236 | /** |
||
237 | * @return string |
||
238 | */ |
||
239 | public function __toString(): string |
||
243 | |||
244 | /** |
||
245 | * @param array $array |
||
246 | * @return bool |
||
247 | */ |
||
248 | private function isAnIndexedArray(array $array): bool |
||
253 | |||
254 | /** |
||
255 | * @param array $params |
||
256 | * @param array ...$keys |
||
257 | * @return array |
||
258 | */ |
||
259 | private function removeFromPath(array $params, ...$keys): array |
||
283 | |||
284 | /** |
||
285 | * Returns the default renderer. |
||
286 | * |
||
287 | * @return QueryStringRendererInterface |
||
288 | */ |
||
289 | public static function getDefaultRenderer(): QueryStringRendererInterface |
||
296 | |||
297 | /** |
||
298 | * Changes default renderer. |
||
299 | * |
||
300 | * @param QueryStringRendererInterface $defaultRenderer |
||
301 | */ |
||
302 | public static function setDefaultRenderer(QueryStringRendererInterface $defaultRenderer): void |
||
306 | |||
307 | /** |
||
308 | * Restores the default renderer. |
||
309 | */ |
||
310 | public static function restoreDefaultRenderer(): void |
||
314 | } |
||
315 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..