Complex classes like Form 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 Form, and based on these observations, apply Extract Interface, too.
| 1 | <?php  | 
            ||
| 15 |   class Form extends Element\Html { | 
            ||
| 16 | |||
| 17 | /**  | 
            ||
| 18 | * @var null|string  | 
            ||
| 19 | */  | 
            ||
| 20 | protected $uid = null;  | 
            ||
| 21 | |||
| 22 | /**  | 
            ||
| 23 | * @var boolean|null  | 
            ||
| 24 | */  | 
            ||
| 25 | protected $validationResult = null;  | 
            ||
| 26 | |||
| 27 | /**  | 
            ||
| 28 | * @var array|null  | 
            ||
| 29 | */  | 
            ||
| 30 | protected $data = null;  | 
            ||
| 31 | |||
| 32 | /**  | 
            ||
| 33 | * @var bool  | 
            ||
| 34 | */  | 
            ||
| 35 | protected $isSubmitted = false;  | 
            ||
| 36 | |||
| 37 | /**  | 
            ||
| 38 | * @var Element\BaseElement[]  | 
            ||
| 39 | */  | 
            ||
| 40 | protected $elements = [];  | 
            ||
| 41 | |||
| 42 | /**  | 
            ||
| 43 | * Default form attributes  | 
            ||
| 44 | *  | 
            ||
| 45 | * @var array  | 
            ||
| 46 | */  | 
            ||
| 47 | protected $attributes = [  | 
            ||
| 48 | 'method' => 'post',  | 
            ||
| 49 | ];  | 
            ||
| 50 | |||
| 51 | |||
| 52 | /**  | 
            ||
| 53 | * @param $name  | 
            ||
| 54 | * @return $this  | 
            ||
| 55 | */  | 
            ||
| 56 | 8 |     public function setName($name) { | 
            |
| 61 | |||
| 62 | |||
| 63 | /**  | 
            ||
| 64 | * @return array  | 
            ||
| 65 | * @throws \Exception  | 
            ||
| 66 | */  | 
            ||
| 67 | 1 |     public function getData() { | 
            |
| 68 | 1 |       if ($this->data === null) { | 
            |
| 69 |         throw new \Exception('Data does not exist!'); | 
            ||
| 70 | }  | 
            ||
| 71 | |||
| 72 | 1 | return $this->data;  | 
            |
| 73 | }  | 
            ||
| 74 | |||
| 75 | |||
| 76 | /**  | 
            ||
| 77 | * @param array|\Iterator $data  | 
            ||
| 78 | * @throws \Exception  | 
            ||
| 79 | */  | 
            ||
| 80 | 14 |     public function setData($data) { | 
            |
| 112 | |||
| 113 | |||
| 114 | /**  | 
            ||
| 115 | * @return string  | 
            ||
| 116 | */  | 
            ||
| 117 | 4 |     public function getMethod() { | 
            |
| 124 | |||
| 125 | |||
| 126 | /**  | 
            ||
| 127 | * @param string $method  | 
            ||
| 128 | * @return $this  | 
            ||
| 129 | */  | 
            ||
| 130 | 2 |     public function setMethod($method) { | 
            |
| 135 | |||
| 136 | |||
| 137 | /**  | 
            ||
| 138 | *  | 
            ||
| 139 | */  | 
            ||
| 140 | 23 |     protected function cleanValidationFlag() { | 
            |
| 143 | |||
| 144 | |||
| 145 | /**  | 
            ||
| 146 | * Check if form is submitted and all elements are valid  | 
            ||
| 147 | *  | 
            ||
| 148 | * @return boolean  | 
            ||
| 149 | */  | 
            ||
| 150 | 9 |     public function isValid() { | 
            |
| 168 | |||
| 169 | |||
| 170 | /**  | 
            ||
| 171 | * Check if form is submitted  | 
            ||
| 172 | *  | 
            ||
| 173 | * @return bool  | 
            ||
| 174 | */  | 
            ||
| 175 | 11 |     public function isSubmitted() { | 
            |
| 178 | |||
| 179 | |||
| 180 | /**  | 
            ||
| 181 | * Return unique id of form  | 
            ||
| 182 | *  | 
            ||
| 183 | * @return string  | 
            ||
| 184 | */  | 
            ||
| 185 | 17 |     public function getUid() { | 
            |
| 192 | |||
| 193 | |||
| 194 | /**  | 
            ||
| 195 | * @return Element\BaseElement[]  | 
            ||
| 196 | */  | 
            ||
| 197 | 4 |     public function getElements() { | 
            |
| 200 | |||
| 201 | |||
| 202 | /**  | 
            ||
| 203 | * @param string $name  | 
            ||
| 204 | * @return Element\BaseElement  | 
            ||
| 205 | * @throws \InvalidArgumentException  | 
            ||
| 206 | */  | 
            ||
| 207 | 2 |     public function getElement($name) { | 
            |
| 213 | |||
| 214 | |||
| 215 | /**  | 
            ||
| 216 | * @param string $name  | 
            ||
| 217 | * @param string|null $text  | 
            ||
| 218 | * @return \Fiv\Form\Element\Input  | 
            ||
| 219 | */  | 
            ||
| 220 | 9 |     public function input($name, $text = null) { | 
            |
| 227 | |||
| 228 | |||
| 229 | /**  | 
            ||
| 230 | * @param string $name  | 
            ||
| 231 | * @param string|null $text  | 
            ||
| 232 | * @return \Fiv\Form\Element\Input  | 
            ||
| 233 | */  | 
            ||
| 234 |     public function password($name, $text = null) { | 
            ||
| 241 | |||
| 242 | |||
| 243 | /**  | 
            ||
| 244 | * @param string $name  | 
            ||
| 245 | * @param null $text  | 
            ||
| 246 | * @return Select  | 
            ||
| 247 | */  | 
            ||
| 248 |     public function select($name, $text = null) { | 
            ||
| 255 | |||
| 256 | |||
| 257 | /**  | 
            ||
| 258 | * @param string $name  | 
            ||
| 259 | * @param string $text  | 
            ||
| 260 | * @return RadioList  | 
            ||
| 261 | */  | 
            ||
| 262 |     public function radioList($name, $text = null) { | 
            ||
| 269 | |||
| 270 | |||
| 271 | /**  | 
            ||
| 272 | * @param string $name  | 
            ||
| 273 | * @param null $text  | 
            ||
| 274 | * @return TextArea  | 
            ||
| 275 | */  | 
            ||
| 276 | 5 |     public function textarea($name, $text = null) { | 
            |
| 283 | |||
| 284 | |||
| 285 | /**  | 
            ||
| 286 | * ```  | 
            ||
| 287 |      * $form->hidden('key', md5($this-user->id . HASH_A); | 
            ||
| 288 | * ```  | 
            ||
| 289 | * @param string $name  | 
            ||
| 290 | * @param null $value  | 
            ||
| 291 | * @return \Fiv\Form\Element\Input  | 
            ||
| 292 | */  | 
            ||
| 293 | 3 |     public function hidden($name, $value = null) { | 
            |
| 301 | |||
| 302 | |||
| 303 | /**  | 
            ||
| 304 | * ```  | 
            ||
| 305 |      * $form->submit('register', 'зареєструватись'); | 
            ||
| 306 | * ```  | 
            ||
| 307 | * @param string $name  | 
            ||
| 308 | * @param null $value  | 
            ||
| 309 | * @return Submit  | 
            ||
| 310 | */  | 
            ||
| 311 | 1 |     public function submit($name, $value = null) { | 
            |
| 318 | |||
| 319 | |||
| 320 | /**  | 
            ||
| 321 | * ```  | 
            ||
| 322 |      * $form->checkbox('subscribe', 'Підписка на новини'); | 
            ||
| 323 | * ```  | 
            ||
| 324 | * @param string $name  | 
            ||
| 325 | * @param string|null $label  | 
            ||
| 326 | * @return Checkbox  | 
            ||
| 327 | */  | 
            ||
| 328 | 2 |     public function checkbox($name, $label = null) { | 
            |
| 335 | |||
| 336 | |||
| 337 | /**  | 
            ||
| 338 | * @param string $name  | 
            ||
| 339 | * @param null $text  | 
            ||
| 340 | * @return CheckboxList  | 
            ||
| 341 | */  | 
            ||
| 342 |     public function checkboxList($name, $text = null) { | 
            ||
| 349 | |||
| 350 | |||
| 351 | /**  | 
            ||
| 352 | * Attach element to this form. Overwrite element with same name  | 
            ||
| 353 | *  | 
            ||
| 354 | * @param Element\BaseElement $element  | 
            ||
| 355 | * @return $this  | 
            ||
| 356 | */  | 
            ||
| 357 | 2 |     public function setElement(Element\BaseElement $element) { | 
            |
| 362 | |||
| 363 | |||
| 364 | /**  | 
            ||
| 365 | * @param Element\BaseElement $element  | 
            ||
| 366 | * @return $this  | 
            ||
| 367 | * @throws \Exception  | 
            ||
| 368 | */  | 
            ||
| 369 | 20 |     public function addElement(Element\BaseElement $element) { | 
            |
| 378 | |||
| 379 | |||
| 380 | /**  | 
            ||
| 381 | * Render full form  | 
            ||
| 382 | *  | 
            ||
| 383 | * @return string  | 
            ||
| 384 | */  | 
            ||
| 385 | 2 |     public function render() { | 
            |
| 388 | |||
| 389 | |||
| 390 | /**  | 
            ||
| 391 | * You can easy rewrite this method for custom design of your forms  | 
            ||
| 392 | *  | 
            ||
| 393 | * @return string  | 
            ||
| 394 | */  | 
            ||
| 395 | 2 |     protected function renderElements() { | 
            |
| 412 | |||
| 413 | |||
| 414 | /**  | 
            ||
| 415 | * @return string  | 
            ||
| 416 | */  | 
            ||
| 417 | 3 |     public function renderStart() { | 
            |
| 443 | |||
| 444 | |||
| 445 | /**  | 
            ||
| 446 | * @return string  | 
            ||
| 447 | */  | 
            ||
| 448 | 3 |     public function renderEnd() { | 
            |
| 451 | |||
| 452 | }  | 
            
Let’s assume that you have a directory layout like this:
. |-- OtherDir | |-- Bar.php | `-- Foo.php `-- SomeDir `-- Foo.phpand let’s assume the following content of
Bar.php:If both files
OtherDir/Foo.phpandSomeDir/Foo.phpare loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.phpHowever, as
OtherDir/Foo.phpdoes not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: