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

Lesson 10 - FormControl - Parent of form controls in PHP

In the previous lesson, Building form framework for PHP - HtmlBuilder, we created an HTML builder which makes generating short HTML fragments easy. In today's tutorial, we'll create an abstract FormControl class which will serve as the parent of all concrete form controls (e.g. for the TextBox).

FormControl

The FormControl class will be the parent for all form controls. It'll contain a validating mechanism and several common properties and methods to ensure that all the form controls have the same interface. Let's go ahead and add an empty class:

abstract class FormControl
{

}

Common properties

We'll start off with the easy stuff. Every control will a name, a label and HTML attributes. We'll add these properties into the class and initialize them in the constructor:

public $label;
public $htmlParams = array();
public $name;

public function __construct($name, $label = '', $htmlParams = array())
{
    $this->name = $name;
    $this->label = $label;
    $this->htmlParams = $htmlParams;
    $this->htmlParams['name'] = $name;
    $this->htmlParams['id'] = $name;
}

We set the control's name and ID right into its HTML parameters. These are HTML attributes which will be added to the element while it's being rendered (converted to HTML code).

While on the topic of simple properties, let's go ahead and add a setter for the ToolTip property. This property is a text which is displayed when you hover the mouse cursor over a control. We set it to the title HTML attribute. Typically, it contains hints at what you should type into the field:

public function setTooltip($toolTip)
{
    $this->htmlParams['title'] = $toolTip;
    return $this;
}

In PHP, we usually don't use getters and setters as much as in languages like Java. However, in this case, they play an important role. Notice how the setter returns a FormControl instance (all setters will do this). In order to set properties without setters, we'd have to write something like this:

$jmenoBox = $form->addTextBox('name', 'Name', true);
$jmenoBox->toolTip = 'Enter your full name';
$jmenoBox->text = 'John Smith';

Thanks to the fact that setters return an instance on which we can call another method, we are able to chain methods easily. Meaning that the code above can be shortened to this:

$form->addTextBox('name', 'Name', true)
     ->setToolTip('Enter your full name')
     ->setText('John Smith');

Hopefully, you agree that this variant is way more readable. Form definitions will be rather long, so briefness matters.

Let's add one more method to the control which will be used to assign a CSS class. Keep in mind that the instance could already have a class set to it:

public function addClass($class)
{
    if (isset($this->htmlParams['class']))
        $this->htmlParams['class'] .= ' ' . $class;
    else
        $this->htmlParams['class'] = $class;
}

Validation

Let's go ahead and add a validation mechanism to the class. The validation mechanism is, without a doubt, the most important part of the class.

Validation rules

We'll implement the validations by adding multiple validation rules to individual form controls. With that in mind, add the $rules array to the class:

private $rules = array();

The individual rules will either be a required-field rule, a regular-expression rule, a password rule, or other similar rule sets. After the form is submitted, every control's rules will be evaluated on both the client and server sides.

The individual rules or validators will be implemented in the FormControl class as simple methods. Another way to do it would be to inherit each rule into a separate class. However, these classes would be very short and similar, so we'll stick to the latter of the two approaches. We'll use the second approach to implement the individual form controls.

Constants

We'll distinguish individual rules using constants:

const RULE_REQUIRED = 0;
const RULE_MAX_LENGTH = 1;
const RULE_PASSWORD = 2;
const RULE_DATETIME = 3;
const RULE_PATTERN = 4;
const RULE_REQUIRED_FILE = 5;

I'm sure you're able to tell what each rule checks. We can create more rules by combining these later.

Adding rules

Every rule will be represented as an associative array. We'll create a private method which adds them into the $rules array:

private function addRule($rule, $validateClient, $validateServer)
{
    $rule['validate_client'] = $validateClient;
    $rule['validate_server'] = $validateServer;
    $this->rules[] = $rule;
    return $this;
}

The method takes an array containing rule data. The other two parameters specify whether the rule should be evaluated on the client and server side. We add the properties based on the parameters and add the rule to the array. We also keep the setter approach and return the instance.

Required-field rule

Let's add a method which adds a required-field rule to a control:

public function addRequiredRule($validateClient = true, $validateServer = true)
{
    return $this->addRule(array(
        'type' => self::RULE_REQUIRED,
        'message' => 'Required field',
    ), $validateClient, $validateServer);
}

The method creates an array which represents the rule. Every rule contains a "type" key with a rule type and a "message" key with an error message. It will be displayed in case the rule is not satisfied, i.e. the field is empty or missing. We add the rule to the $rules array using the private method.

We'll create other methods which add other rules in the same way.

Maximal-length rule

The maximal-length rule is later translated to the maxlength attribute on the client-side. It'll look like the following:

public function addMaxLengthRule($maxLength, $validateClient = true, $validateServer = true)
{
    return $this->addRule(array(
        'type' => self::RULE_MAX_LENGTH,
        'max_length' => $maxLength,
        'message' => 'The maximal length of the value is ' . $maxLength,
    ), $validateClient, $validateServer);
}

Regular-expression rule

The key rule is the rule which checks whether a field's content matches a regular expression.

public function addPatternRule($pattern, $validateClient = true, $validateServer = true)
{
    return $this->addRule(array(
        'type' => self::RULE_PATTERN,
        'pattern' => $pattern,
        'message' => 'The value has an invalid format',
    ), $validateClient, $validateServer);
}

We'll use this rule very often in other rules. We'll add several constants for the most frequent regular expressions to the class:

const PATTERN_URL = '(http|https)://.*';
const PATTERN_INTEGER = '[0-9]+';
const PATTERN_EMAIL = '[a-z0-9._-]+@[a-z0-9.-]+\.[a-z]{2,4}$';

We'll define rules with a "^" character at the beginning and a "$" character at the end (we'll automate this process later on). In the next lesson, Finishing the FormControl class in PHP, we'll finish the class by adding methods for the remaining rules and their evaluation.


 

Previous article
Building form framework for PHP - HtmlBuilder
All articles in this section
Libraries for PHP
Skip article
(not recommended)
Finishing the FormControl class in PHP
Article has been written for you by David Capka Hartinger
Avatar
User rating:
1 votes
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