Get up to 80 % extra points for free! More info:

Lesson 8 - Building form framework for PHP - Motivation

Welcome to this new lesson on creating libraries for PHP! Today, we'll start working on a larger, yet still minimalistic library, which will handle all issues regarding forms for us. Forms in web applications represent a significant part of the whole. Therefore, a form framework will save us a lot of time and effort. Its creation will take up several lessons and it'll be slightly advanced in functionality. With this in mind, I've decided to dedicate all of today's lesson to motivate you all so you could see all of the benefits that come with it. To be clear, the result will be more of a small framework than a library, however, I'll use these terms interchangeably.

Forms in plain PHP

Let's go over how many things we have to do in a plain PHP in order to save values from several form fields into the database. We'll demonstrate everything on a simple form that simulates ordering a car:

Creating forms in PHP - Libraries for PHP

HTML code

When we make forms, we usually start with the HTML code. We want the form to look nice and responsive, so we'll have to add additional div and span elements. We'll use HTML 5 attributes for client-side validations, which will keep things as simple as possible. Our HTML code could look something like this:

<form method="POST" id="car-order" class="fancyform">
    <div class="form-component">
        <label for="name">Name</label>
        <input name="name" id="name" required="required" type="text"/>
        <div class="clear"></div>
    </div>
    <div class="form-component">
        <label for="email">Email</label>
        <input name="email" id="email" type="email" />
        <div class="clear"></div>
    </div>
    <div class="form-component">
        <label for="car-brand">Brand</label>
        <select name="car_brand" id="car_brand" required="required">
            <option value="ford">Ford</option>
            <option value="bmw">BMW</option>
            <option value="audi">Audi</option>
        </select>
        <div class="clear"></div>
    </div>
    <div class="form-component">
        <label for="drivetrain">Drivetrain</label>
        <select name="drivetrain" id="drivetrain" required="required">
            <option value="front-wheel">Front-wheel</option>
            <option value="rear-wheel">Rear-wheel</option>
            <option value="4x4">4x4</option>
        </select>
        <div class="clear"></div>
    </div>
    <div class="form-component">
        <label for="payment_method">Payment method</label>
        <div name="zpusob_platby" id="payment_method" class="radio-horizontal">
            <span>
                <input name="payment_method" id="payment_method1" value="wiretransfer" type="radio" checked="checked"/>
                <label for="payment_method1">Wiretransfer</label>
            </span>
            <span>
                <input name="payment_method" id="payment_method2" value="check" type="radio"/>
                <label for="payment_method2">Check</label>
            </span>
            <span>
                <input name="payment_method" id="payment_method3" value="cash" type="radio"/>
                <label for="payment_method3">In cash</label>
            </span>
        </div>
        <div class="clear"></div>
    </div>
    <div class="form-component">
        <label for="note">Note</label>
        <textarea name="note" id="note"></textarea>
        <div class="clear"></div>
    </div>
    <div class="form-component">
        <label for="equipment">Equipment</label>
        <div name="equipment" id="equipment" class="radio-horizontal">
            <span>
                <input type="checkbox" name="abs" value="1" id="equipmentabs"/>
                <label for="equipmentabs">ABS</label>
            </span>
            <span>
                <input type="checkbox" name="wipers" value="1" id="equipmentwipers"/>
                <label for="equipmentwipers">Windshield wipers</label>
            </span>
            <span><input type="checkbox" name="asr" value="1" id="equipmentasr"/>
                <label for="equipmentasr">ASR</label>
            </span>
            <span>
                <input type="checkbox" name="eps" value="1" id="equipmenteps"/>
                <label for="equipmenteps">EPS</label>
            </span>
        </div>
        <div class="clear"></div>
    </div>
    <div class="form-buttons">
        <input name="order" id="order" value="Order" type="submit"/>
    </div>
</form>

The code is 74 lines long and only displays seven fields, it's not very effective. Things could only get worse from then on (without using a framework).

Validation

We'd then have to re-validate the data on the server-side. We have to because we can't rely solely on the client's validation. The main purpose is for clients to see what they entered wrong, if applicable. To avoid storing inconsistent data into the database, we'd have to perform a simple server-side validation:

if (isset($_POST['name']) && ($_POST['name']) &&
    (!isset($_POST['email']) || (preg_match('/^([a-zA-Z0-9])+([a-zA-Z0-9\._-])*@([a-zA-Z0-9_-])+([a-zA-Z0-9\._-]+)+$/u', $_POST['email']))) &&
    isset($_POST['car_brand']) && ($_POST['car_brand']) &&
    isset($_POST['drivetrain']) && ($_POST['drivetrain']) &&
    isset($_POST['payment_method']) &&
    isset($_POST['note']) &&
    isset($_POST['equipment']))

We're now at 81 lines.

Saving values into database

Then, we'd have to save the order into the database:

Db::dotaz('
    INSERT INTO `order` (name, email, car_brand, drivetrain, payment_method, note, equipment)
    VALUES
    (?, ?, ?, ?, ?, ?, ?)
', $_POST['name'], $_POST['email'], $_POST['car_brand'], $_POST['drivetrain'], $_POST['payment_method'], $_POST['note'], $_POST['equipment']);

That's 86 lines total needed to add seven fields into the database!

Form framework

Now that that's been established, let's go over what the same, exact form would look like using our form framework.

Form definition

We'll create the form as an instance of the Form class and add individual fields:

$form = new Form('car-order');
$form->addTextBox('name', 'Name', true);
$form->addEmailBox('email', 'Email', false);
$form->addComboBox('car_brand', 'Brand', true)
    ->setValues(array(
        'Ford' => 'ford',
        'BMW' => 'bmw',
        'Audi' => 'audi',
    ));
$form->addListBox('drivetrain', 'Drivetrain', true, false)
    ->setValues(array(
        'Front-wheel' => 'front-wheel',
        'Rear-wheel' => 'rear-wheel',
        '4x4' => '4x4',
    ));
$form->addRadioGroup('payment_method', 'Payment method', true)
    ->setValues(array(
        'Wiretransfer' => 'wiretransfer',
        'Check' => 'check',
        'In cash' => 'cash',
    ));
$form->addTextArea('note', 'Note', false);
$form->addCheckList('equipment', 'Equipment')
    ->setValues(array(
        'ABS' => 'abs',
        'Windshield wipers' => 'wipers',
        'ASR' => 'asr',
        'EPS' => 'eps',
    ));
$form->addButton('order', 'Order');

At this point, we have 29 lines of code for seven fields, which is a good ratio. All of the additional lines simply define the items that are to be chosen.

HTML code

The HTML code will be generated automatically. All we'll have to do is call the render() method on the form instance:

<?= $form->render() ?>

Validation

The server-side validations will be performed automatically after the first attempt to retrieve values from the form occurs.

Saving values into database

If we use the form framework along with ICT.social's database wrapper, we'd be able to save data into the database like this:

Db::insert('order', $form->getData());

Total length: 31 lines as opposed to 86 lines without using the framework. We've removed more than 60% of the code and got the same results. We could make two more forms in the same amount of time it would take to make one otherwise. The example was greatly simplified. The difference would be even more apparent on larger, more complex forms.

Additional features

The form framework has many other features which I didn't want to throw at you quite yet:

- Additional fields - Additional form fields such as ListBoxes, FileBoxes, PasswordBoxes and so on.
- Partial rendering - A form can also be partially rendered in case you want to set up a different layout, insert an image or headings somewhere in a form, split the form into multiple pages, add special JavaScript buttons, etc.
- Multiple forms - The library can easily handle multiple forms on a single page.
- Filtering data - You can use the getData() method to retrieve a specific part of the data. This method is useful when there are fields in a form that you don't want to save into the database, e.g. a captcha.
- Filling data in - You can fill a form in with the data retrieved from a query using the setData() method. This method comes in handy when editing entities.

The most important thing to take away from this lesson is that the library is minimalistic and is designed in a way that makes extending and modifying it simple. I hope this lesson has motivated you enough to want to actually make this framework. In the next lesson, Building form framework for PHP - HtmlBuilder, we'll create the first utility class for the form framework, the HtmlBuilder class.


 

Previous article
Finishing ArrayUtils library for PHP
All articles in this section
Libraries for PHP
Skip article
(not recommended)
Building form framework for PHP - HtmlBuilder
Article has been written for you by David Capka Hartinger
Avatar
User rating:
No one has rated this quite yet, be the first one!
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities