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 |
||
| 25 | class Request implements RequestInterface |
||
| 26 | { |
||
| 27 | /** @type string $method request method */ |
||
| 28 | protected $method; |
||
| 29 | /** @type string $pathinfo request path info */ |
||
| 30 | protected $pathinfo; |
||
| 31 | /** @type array $details request details */ |
||
| 32 | protected $details; |
||
| 33 | |||
| 34 | |||
| 35 | /** |
||
| 36 | * Generates a request object from globals |
||
| 37 | * |
||
| 38 | * @return RequestInterface request object |
||
| 39 | * |
||
| 40 | * @todo fixme: start session if necessary |
||
| 41 | */ |
||
| 42 | public static function generateFromGlobals() |
||
| 106 | |||
| 107 | /** |
||
| 108 | * Initializes a request |
||
| 109 | * |
||
| 110 | * @param string $uMethod method |
||
| 111 | * @param string $uPathInfo pathinfo |
||
| 112 | * @param array|null $uDetails available keys: get, post, files, server, session, cookies, headers |
||
| 113 | * |
||
| 114 | * @return Request request object |
||
| 115 | */ |
||
| 116 | public function __construct($uMethod, $uPathInfo, array $uDetails = null) |
||
| 128 | |||
| 129 | /** |
||
| 130 | * Gets endpoint |
||
| 131 | * |
||
| 132 | * For http, it's scheme://host:port/directory/ |
||
| 133 | * |
||
| 134 | * @return string |
||
| 135 | */ |
||
| 136 | public function getEndpoint() |
||
| 145 | |||
| 146 | /** |
||
| 147 | * Gets method |
||
| 148 | * |
||
| 149 | * @return string |
||
| 150 | */ |
||
| 151 | public function getMethod() |
||
| 155 | |||
| 156 | /** |
||
| 157 | * Gets path info |
||
| 158 | * |
||
| 159 | * @return string |
||
| 160 | */ |
||
| 161 | public function getPathInfo() |
||
| 165 | |||
| 166 | /** |
||
| 167 | * Gets remote ip |
||
| 168 | * |
||
| 169 | * @return string |
||
| 170 | */ |
||
| 171 | public function getRemoteIp() |
||
| 187 | |||
| 188 | /** |
||
| 189 | * Gets accepted content-types |
||
| 190 | * |
||
| 191 | * @return array |
||
| 192 | */ |
||
| 193 | public function getAcceptedContentTypes() |
||
| 197 | |||
| 198 | /** |
||
| 199 | * Gets accepted charsets |
||
| 200 | * |
||
| 201 | * @return array |
||
| 202 | */ |
||
| 203 | public function getAcceptedCharsets() |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Gets accepted encodings |
||
| 210 | * |
||
| 211 | * @return array |
||
| 212 | */ |
||
| 213 | public function getAcceptedEncodings() |
||
| 217 | |||
| 218 | /** |
||
| 219 | * Gets accepted languages |
||
| 220 | * |
||
| 221 | * @return array |
||
| 222 | */ |
||
| 223 | public function getAcceptedLanguages() |
||
| 227 | |||
| 228 | /** |
||
| 229 | * Determines whether the request is asynchronous or not |
||
| 230 | * |
||
| 231 | * @return bool |
||
| 232 | */ |
||
| 233 | public function isAsynchronous() |
||
| 241 | |||
| 242 | /** |
||
| 243 | * Gets session id |
||
| 244 | * |
||
| 245 | * @return string |
||
| 246 | */ |
||
| 247 | public function getSessionId() |
||
| 251 | |||
| 252 | /** |
||
| 253 | * Gets an item from GET collection |
||
| 254 | * |
||
| 255 | * @param string $uKey the key for the value |
||
| 256 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 257 | * |
||
| 258 | * @return mixed value for the key |
||
| 259 | */ |
||
| 260 | View Code Duplication | public function get($uKey, $uDefault = null) |
|
| 268 | |||
| 269 | /** |
||
| 270 | * Gets an item from POST collection |
||
| 271 | * |
||
| 272 | * @param string $uKey the key for the value |
||
| 273 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 274 | * |
||
| 275 | * @return mixed value for the key |
||
| 276 | */ |
||
| 277 | View Code Duplication | public function post($uKey, $uDefault = null) |
|
| 285 | |||
| 286 | /** |
||
| 287 | * Gets an item from FILES collection |
||
| 288 | * |
||
| 289 | * @param string $uKey the key for the value |
||
| 290 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 291 | * |
||
| 292 | * @return mixed value for the key |
||
| 293 | */ |
||
| 294 | View Code Duplication | public function file($uKey, $uDefault = null) |
|
| 303 | |||
| 304 | /** |
||
| 305 | * Gets an item from GET/POST/FILE collections |
||
| 306 | * |
||
| 307 | * @param string $uKey the key for the value |
||
| 308 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 309 | * |
||
| 310 | * @return mixed value for the key |
||
| 311 | */ |
||
| 312 | public function data($uKey, $uDefault = null) |
||
| 322 | |||
| 323 | /** |
||
| 324 | * Gets an item from SERVER collection |
||
| 325 | * |
||
| 326 | * @param string $uKey the key for the value |
||
| 327 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 328 | * |
||
| 329 | * @return mixed value for the key |
||
| 330 | */ |
||
| 331 | View Code Duplication | public function server($uKey, $uDefault = null) |
|
| 340 | |||
| 341 | /** |
||
| 342 | * Gets an item from SESSION collection |
||
| 343 | * |
||
| 344 | * @param string $uKey the key for the value |
||
| 345 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 346 | * |
||
| 347 | * @return mixed value for the key |
||
| 348 | */ |
||
| 349 | View Code Duplication | public function session($uKey, $uDefault = null) |
|
| 358 | |||
| 359 | /** |
||
| 360 | * Gets an item from COOKIE collection |
||
| 361 | * |
||
| 362 | * @param string $uKey the key for the value |
||
| 363 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 364 | * |
||
| 365 | * @return mixed value for the key |
||
| 366 | */ |
||
| 367 | View Code Duplication | public function cookie($uKey, $uDefault = null) |
|
| 376 | |||
| 377 | /** |
||
| 378 | * Gets an item from HEADER collection |
||
| 379 | * |
||
| 380 | * @param string $uKey the key for the value |
||
| 381 | * @param mixed $uDefault default value if the key does not exist in the collection |
||
| 382 | * |
||
| 383 | * @return mixed value for the key |
||
| 384 | */ |
||
| 385 | View Code Duplication | public function header($uKey, $uDefault = null) |
|
| 394 | |||
| 395 | /** |
||
| 396 | * Checks if item is in the specified collection |
||
| 397 | * |
||
| 398 | * @param string|null $uCollection the key of the collection |
||
| 399 | * @param string $uKey the key for the value |
||
| 400 | * |
||
| 401 | * @return bool true if item exists in the collection |
||
| 402 | */ |
||
| 403 | public function has($uCollection, $uKey) |
||
| 407 | |||
| 408 | /** |
||
| 409 | * Gets all items from GET/POST/FILE/SERVER/SESSION/COOKIE/HEADER collections |
||
| 410 | * |
||
| 411 | * @param string|null $uCollection the key if only one collection's items are needed |
||
| 412 | * |
||
| 413 | * @return array available collections: get, post, files, server, session, cookies, headers |
||
| 414 | */ |
||
| 415 | public function all($uCollection = null) |
||
| 423 | } |
||
| 424 |
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: