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 Request 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 Request, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
13 | class Request { |
||
14 | use Module; |
||
15 | |||
16 | protected static $body, |
||
|
|||
17 | $accepts; |
||
18 | |||
19 | /** |
||
20 | * Handle Content Negotiation requests |
||
21 | * |
||
22 | * @param string $key The name of the negotiation subject |
||
23 | * @param string $choices A query string for the negotiation choices (See RFC 7231) |
||
24 | * |
||
25 | * @return Object The preferred content if $choices is empty else return best match |
||
26 | */ |
||
27 | public static function accept($key='type',$choices='') { |
||
28 | if (null === static::$accepts) static::$accepts = [ |
||
29 | 'type' => new Negotiation(isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : ''), |
||
30 | 'language' => new Negotiation(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : ''), |
||
31 | 'encoding' => new Negotiation(isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? $_SERVER['HTTP_ACCEPT_ENCODING'] : ''), |
||
32 | 'charset' => new Negotiation(isset($_SERVER['HTTP_ACCEPT_CHARSET']) ? $_SERVER['HTTP_ACCEPT_CHARSET'] : ''), |
||
33 | ]; |
||
34 | return empty(static::$accepts[$key]) |
||
35 | ? false |
||
36 | : ( empty($choices) |
||
37 | ? static::$accepts[$key]->preferred() |
||
38 | : static::$accepts[$key]->best($choices) |
||
39 | ); |
||
40 | } |
||
41 | |||
42 | /** |
||
43 | * Retrive a value from generic input (from the $_REQUEST array) |
||
44 | * Returns all elements if you pass `null` as $key |
||
45 | * |
||
46 | * @param string $key The name of the input value |
||
47 | * |
||
48 | * @return Object The returned value or $default. |
||
49 | */ |
||
50 | public static function input($key=null,$default=null){ |
||
53 | |||
54 | /** |
||
55 | * Retrive a value from environment (from the $_ENV array) |
||
56 | * Returns all elements if you pass `null` as $key |
||
57 | * |
||
58 | * @param string $key The name of the input value |
||
59 | * |
||
60 | * @return Object The returned value or $default. |
||
61 | */ |
||
62 | public static function env($key=null,$default=null){ |
||
65 | |||
66 | /** |
||
67 | * Retrive a value from server (from the $_SERVER array) |
||
68 | * Returns all elements if you pass `null` as $key |
||
69 | * |
||
70 | * @param string $key The name of the input value |
||
71 | * |
||
72 | * @return Object The returned value or $default. |
||
73 | */ |
||
74 | public static function server($key=null,$default=null){ |
||
75 | return $key ? (isset($_SERVER[$key]) ? $_SERVER[$key] : (is_callable($default)?call_user_func($default):$default)) : $_SERVER; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Retrive a value from generic input (from the $_POST array) |
||
80 | * Returns all elements if you pass `null` as $key |
||
81 | * |
||
82 | * @param string $key The name of the input value |
||
83 | * |
||
84 | * @return Object The returned value or $default. |
||
85 | */ |
||
86 | public static function post($key=null,$default=null){ |
||
89 | |||
90 | /** |
||
91 | * Retrive a value from generic input (from the $_GET array) |
||
92 | * Returns all elements if you pass `null` as $key |
||
93 | * |
||
94 | * @param string $key The name of the input value |
||
95 | * |
||
96 | * @return Object The returned value or $default. |
||
97 | */ |
||
98 | public static function get($key=null,$default=null){ |
||
101 | |||
102 | /** |
||
103 | * Retrive uploaded file (from the $_FILES array) |
||
104 | * Returns all uploaded files if you pass `null` as $key |
||
105 | * |
||
106 | * @param string $key The name of the input value |
||
107 | * |
||
108 | * @return Object The returned value or $default. |
||
109 | */ |
||
110 | public static function files($key=null,$default=null){ |
||
111 | return $key ? (isset($_FILES[$key]) ? $_FILES[$key] : (is_callable($default)?call_user_func($default):$default)) : $_FILES; |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * Retrive cookie (from the $_COOKIE array) |
||
116 | * Returns all cookies if you pass `null` as $key |
||
117 | * |
||
118 | * @param string $key The name of the input value |
||
119 | * |
||
120 | * @return Object The returned value or $default. |
||
121 | */ |
||
122 | public static function cookie($key=null,$default=null){ |
||
125 | |||
126 | /** |
||
127 | * Returns the current host and port (omitted if port 80), complete with protocol (pass `false` to omit). |
||
128 | * |
||
129 | * @return string |
||
130 | */ |
||
131 | public static function host($protocol=true){ |
||
148 | |||
149 | /** |
||
150 | * Returns the current request URL, complete with host and protocol. |
||
151 | * |
||
152 | * @return string |
||
153 | */ |
||
154 | public static function URL(){ |
||
157 | |||
158 | /** |
||
159 | * Retrive header |
||
160 | * Returns all headers if you pass `null` as $key |
||
161 | * |
||
162 | * @param string $key The name of the input value |
||
163 | * |
||
164 | * @return Object The returned value or null. |
||
165 | */ |
||
166 | public static function header($key=null,$default=null){ |
||
170 | |||
171 | /** |
||
172 | * Returns the current request URI. |
||
173 | * |
||
174 | * @param boolean $relative If true, trim the URI relative to the application index.php script. |
||
175 | * |
||
176 | * @return string |
||
177 | */ |
||
178 | public static function URI($relative=true){ |
||
203 | |||
204 | /** |
||
205 | * Returns the current base URI (The front-controller directory) |
||
206 | * |
||
207 | * @return string |
||
208 | */ |
||
209 | public static function baseURI(){ |
||
212 | |||
213 | /** |
||
214 | * Returns the HTTP Method |
||
215 | * |
||
216 | * @return string |
||
217 | */ |
||
218 | public static function method(){ |
||
221 | |||
222 | /** |
||
223 | * Returns the remote IP |
||
224 | * |
||
225 | * @return string |
||
226 | */ |
||
227 | public static function IP(){ |
||
241 | |||
242 | /** |
||
243 | * Returns the remote UserAgent |
||
244 | * |
||
245 | * @return string |
||
246 | */ |
||
247 | public static function UA(){ |
||
250 | |||
251 | /** |
||
252 | * Returns request body data, convert to object if content type is JSON |
||
253 | * Gives you all request data if you pass `null` as $key |
||
254 | * |
||
255 | * @param string $key The name of the key requested |
||
256 | * |
||
257 | * @return mixed The request body data |
||
258 | */ |
||
259 | public static function data($key=null,$default=null){ |
||
275 | |||
276 | } |
||
277 |
Only declaring a single property per statement allows you to later on add doc comments more easily.
It is also recommended by PSR2, so it is a common style that many people expect.