Yes, another PHP form builder... I wrote this solely to demonstrate OOP principles.
My questions are:
- Could this be written better? OOP-wise.
- How could I better implement error handling?
Index.php
<?php require __DIR__ . '/vendor/autoload.php'; use FormBuilder\FormGenerator as Form; use FormBuilder\TextField as TextField; use FormBuilder\InputErrors as Errors; $action = '/index.php'; $method = 'POST'; $form = new Form($action, $method); $form->addField((new TextField('name'))->addRule(new Rules\MinLenght(3, 'Name too short')) ->addRule(new Rules\MaxLenght(13, 'Name too long')) ->setAttribute('required')); $form->addField(new TextField('phone_number')); $form->addField(new TextField('email_address')); if (!empty($_POST)) $form->validateForm(); $form->display();
Core/FormGenerator.php
<?php namespace FormBuilder; class FormGenerator { private $action; private $method; private $fields = []; public function __construct(string $action, string $method) { $this->action = $action; $this->method = $method; } public function addField(object $field) { array_push($this->fields, $field); } public function display() { echo '<form method="', $this->method, '" action="', $this->action, '">'; foreach ($this->fields as $field) $field->generateElement(); echo '<input type="submit"></input>'; echo '</form>'; } public function validateForm() { foreach ($this->fields as $field) { $field->validateField(); } } }
Core/Input.php
<?php namespace FormBuilder; Abstract class Input { protected $attributes = []; protected $rules = []; protected $label = null; protected $content = null; public function __construct($nameAttribute) { $this->attributes['name'] = $nameAttribute; } public function setAttribute($name, $value = null) { if ($value) $this->attributes[$name] = $value; else $this->attributes[$name] = null; return $this; } public function addRule($rules) { array_push($this->rules, $rules); return $this; } public function setLabel($label) { $this->label = $label; return $this; } public function validateField() { foreach ($this->rules as $rule) { $rule->validate($this->attributes['name']); } } protected function attributesToString($attributes) { $string = ''; foreach($attributes as $name => $value) { if ($value) $string .= ' ' . $name . '="' . $value . '"'; else $string .= ' ' . $name . ' '; } return $string; } abstract public function generateElement(); }
Core/TextField.php
<?php namespace FormBuilder; use FormBuilder\InputErrors as Errors; class TextField extends Input { public function generateElement() { echo '<input type="text"' . $this->attributesToString($this->attributes) . '>'; if (Errors::get($this->attributes['name'])) { echo '<p>' . Errors::get($this->attributes['name']) . '</p>'; } if ($this->label) { echo '<label for="' . $this->attributes['name'] . '">' . $this->label . '</label>'; } } }
Core/InputErrors.php
<?php namespace FormBuilder; class InputErrors { private static $errors = []; public static function set($inputName, $error) { self::$errors[$inputName] = $error; } public static function get($inputName) { return (isset(self::$errors[$inputName])) ? self::$errors[$inputName] : False; } public static function dump() { return self::$errors; } }
Core/Rules/MaxLenght.php
<?php namespace Rules; use FormBuilder\InputErrors as InputErrors; class MaxLenght { private $maxLenght; private $errorMessage; public function __construct($maxLenght, $errorMessage) { $this->maxLenght = $maxLenght; $this->errorMessage = $errorMessage; } public function validate($inputName) { if (strlen($_POST[$inputName]) > $this->maxLenght) { InputErrors::set($inputName, $this->errorMessage); } } }
Core/Rules/MinLenght.php
<?php namespace Rules; use FormBuilder\InputErrors as InputErrors; class MinLenght { private $minLenght; private $errorMessage; public function __construct($minLenght, $errorMessage) { $this->minLenght = $minLenght; $this->errorMessage = $errorMessage; } public function validate($inputName) { if (strlen($_POST[$inputName]) < $this->minLenght) { InputErrors::set($inputName, $this->errorMessage); } } }