Skip to main content
2 of 4
edited tags
200_success
  • 145.6k
  • 22
  • 191
  • 481

OOP PHP form builder with validation

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

}