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);
}
}
}