Building a PHP 5 Form Processor: Using the Form Processor Package

Welcome to the last part of the series “Building a PHP 5 form processor.” In three parts, this series goes through the development of an extensible form processor package in PHP 5, explaining its benefits and demonstrating its implementation.

Introduction

Returning for a moment to the previous article, I put my effort into writing a reusable class, which originally exposed a set of predefined methods, useful for performing server-side validation on user-supplied data.

If you’ve been reading the earlier tutorials, then you know that the goal of this series was developing a PHP form processing package, comprised of two highly generic components. The first component is a form generator module, which presents a bunch of classes for programmatically constructing online forms, offering optional basic client-side validation capabilities. The second one is a form validation module that exposes a series of methods for validating user-provided data. Together, both components can be implemented as a standalone package within a PHP application, in order to build and quickly process web forms.

Now, before proceeding further, let’s spend a few minutes discussing the objectives of this last tutorial, so you can have an accurate idea of how I’ll use this form processing library. Basically, I’ll set up an example, in order to demonstrate the functionality of both modules within a real application. First, I’ll use the corresponding classes for constructing an online form, then I’ll instruct the application to apply client-side validation on some of the form fields. Finally I’ll have the application perform server-side checking on the form data, by displaying the appropriate error messages if any values entered on the form eventually fail to pass the verification process.

So, that’s the theory. Let’s now turn our attention to writing the hands-on example. You’ll have a really good time. Let’s go!

{mospagebreak title=Getting started: constructing programmatically an online form}

One of the best things about building an online form using an object-oriented approach is that the overall rendering process may be considerably simplified to instantiating a few form objects and deciding the best layout for them. Keeping this concept in mind, I’ll construct a simple contact form, which presents some of the usual text boxes, such as “First Name”, “Last Name”, “Email” and “Comments”, as you’ve seen hundreds of times. However, all of the building process will be driven by the classes that I developed in the first part of this series, including client-side validation. Take a look at the fragment of code below:

try{
    // include ‘formElement’ class
    require_once ‘form_element.php';
    // include ‘formGenerator’ class
    require_once ‘form_generator.php';
    // include ‘JSGenerator’ class
    require_once ‘js_generator.php';
    // instantiate form generator object
    $fg=new formGenerator();
    $fg->addFormPart(‘<table>’);
    $fg->addFormPart(‘<tr><td>First Name</td><td>’);
    $fg->addElement(‘text’,array
(‘name’=>’fname’,’required’=>array(‘empty’,’Enter your First name
(at least 4 characters)’)));
    $fg->addFormPart(‘</tr>’);
    $fg->addFormPart(‘<tr><td>Last Name</td><td>’);
    $fg->addElement(‘text’,array
(‘name’=>’lname’,’required’=>array(‘empty’,’Enter your Last name
(at least 4 characters)’)));
    $fg->addFormPart(‘</tr>’);
    $fg->addFormPart(‘<tr><td>Email</td><td>’);
    $fg->addElement(‘text’,array
(‘name’=>’email’,’required’=>array(‘email’,’Enter a valid email
address’)));
    $fg->addFormPart(‘</tr>’);
    $fg->addFormPart(‘<tr><td>Comments</td><td>’);
    $fg->addElement(‘textarea’,array
(‘name’=>’comments’,’rows’=>’10’,’cols’=>’20’));
    $fg->addFormPart(‘</tr>’);
    $fg->addFormPart(‘<tr><td>&nbsp;</td><td>’);
    $fg->addElement(‘submit’,array(‘name’=>’send’,’value’=>’Send
Data’));
    $fg->addFormPart(‘</tr></table>’);
    echo $fg->display();
}
catch(Exception $e){
    echo $e->getMessage();
    exit();
}

As shown in the fragment of code above, I’ve included the corresponding class files for rendering form elements, as well as for performing client-side validation. After loading these classes, I instantiated a “formGenerator” object and simply proceeded to build the pertinent form.

As you can see, I’ve utilized the “addFormPart()” method, in order to use a simple (X)HTML table for laying out each form element on the web page. Please notice how the class is instructed to perform client-side validation on the “fname”, “lname” and “email” fields, through their “required” attribute, and in all these cases, the corresponding error message is passed as an argument to the class method. After adding up all the form elements, the form is simply displayed by calling the “display()” method.

If you run the above snippet, the output looks like this:

Although the above screenshot depicts a rather crude implementation of the form rendering process, it actually demonstrates how the form has been constructed and how JavaScript validation is performed on each of the required fields. At this point, the functionality of these classes for building online forms in a very quick way should be clear to you.

Now that you understand how these classes work, the next step for setting up the example rests on demonstrating how the “validator” module checks, on the server, the validity of the data entered on required fields.

{mospagebreak title=Performing server-side validation: implementing the “validator” module}

As you know, in addition to basic client-side validation performed before submitting the form, the “validator” module, which I developed in the previous article, exposes some handy methods for verifying on the server whether user-supplied data is valid or not. It’s precisely for this reason that I’ll write a little piece of code, which validates the data entered in the required fields. The checking script looks like this:

if($_POST['send']){
    // instantiate form validator object
    $fv=new formValidator();
    $fv->validateEmpty(‘fname’,’Enter your first name (Min: 4
characters)’);
    $fv->validateEmpty(‘lname’,’Enter your last name (Min: 4
characters)’);
    $fv->validateEmail(‘email’,’Enter a valid email address’);
    // check for errors
    if($fv->checkErrors()){
        // display errors
        echo ‘<h2>Resubmit the form after correcting the
following errors:</h2>';
        echo $fv->displayErrors();
    }
    else {
        echo ‘<h2>Thank you for submitting your data!</h2>';
    }
}

If you study the above script, you’ll see that after submitting the form, a form “validator” object is instantiated, in order to verify the data of each required field. In this example I’ve used the “validateEmpty()” method for checking whether the values entered for “First Name” and “Last Name” are empty strings or not. Similarly, the “email” field is checked by the “validateEmail()” method.

After running the server-side checking script and assuming that invalid data was submitted by the form, the output might look like this:

As you can see, the “formValidator” class does a decent job validating the required fields. Of course, the look and feel for displaying error messages should be styled properly, but I guess you have a pretty clear idea of how the server-side validation process works.

Having demonstrated the nice capabilities of both form processing modules, it’s time to show how they fit into a single script. Considering this situation, jump into the next section to learn how these modules are implemented on the same PHP file.

{mospagebreak title=Gluing the pieces: putting the form processing modules to work together}

Since you’ve already seen how each independent module works, next I’ll integrate them within the same PHP script. The end result of this will be a code fragment that displays the online form; after it’s been submitted, server validation is applied to each mandatory field. Take a closer look:

// if form was submitted perform server-side validation
if($_POST['send']){
    // instantiate form validator object
    $fv=new formValidator();
    $fv->validateEmpty(‘fname’,’Enter your first name (Min: 4
characters)’);
    $fv->validateEmpty(‘lname’,’Enter your last name (Min: 4
characters)’);
    $fv->validateEmail(‘email’,’Enter a valid email address’);
    // check for errors
    if($fv->checkErrors()){
        // display errors
        echo ‘<h2>Resubmit the form after correcting the
following errors:</h2>';
        echo $fv->displayErrors();
    }
    else {
        echo ‘<h2>Thank you for submitting your data!</h2>';
    }
}
// create and display form
else {
    try{
        // instantiate form generator object
        $fg=new formGenerator();
        $fg->addFormPart(‘<table>’);
        $fg->addFormPart(‘<tr><td>First Name</td><td>’);
        $fg->addElement(‘text’,array
(‘name’=>’fname’,’required’=>array(‘empty’,’Enter your First name
(at least 4 characters)’)));
        $fg->addFormPart(‘</tr>’);
        $fg->addFormPart(‘<tr><td>Last Name</td><td>’);
        $fg->addElement(‘text’,array
(‘name’=>’lname’,’required’=>array(‘empty’,’Enter your Last name
(at least 4 characters)’)));
        $fg->addFormPart(‘</tr>’);
        $fg->addFormPart(‘<tr><td>Email</td><td>’);
        $fg->addElement(‘text’,array
(‘name’=>’email’,’required’=>array(‘email’,’Enter a valid email
address’)));
        $fg->addFormPart(‘</tr>’);
        $fg->addFormPart(‘<tr><td>Comments</td><td>’);
        $fg->addElement(‘textarea’,array
(‘name’=>’comments’,’rows’=>’10’,’cols’=>’20’));
        $fg->addFormPart(‘</tr>’);
        $fg->addFormPart(‘<tr><td>&nbsp;</td><td>’);
        $fg->addElement(‘submit’,array
(‘name’=>’send’,’value’=>’Send Data’));
        $fg->addFormPart(‘</tr></table>’);
        echo $fg->display();
    }
    catch(Exception $e){
        echo $e->getMessage();
        exit();
    }
}

Here, notice how I use the “formValidator” class to check the validity of the data entered into required fields, after the form has been submitted. If any errors are found during the checking process, the warning messages are displayed on the page. Otherwise, the script confirms that submitted data is correct.

Similarly, the second part of the script constructs the corresponding form and displays it on the web page, by specifying the form elements to be rendered, as well as the fields on which client-side validation is performed. At this point, you’ll agree the overall script is very readable and each of their sections clearly shows what’s going on.

Now, the form processing package that I originally planned to build is completed. As you probably understand, with a wealth of classes behind the scenes charged with the hard work of rendering and processing forms, the use of this library demands only writing some lines of compact and readable code.

To provide you with the complete set of classes developed during the course of this series, the last section shows the source code for the entire form processor. So, let’s go there.

{mospagebreak title=The complete application at a glance: listing the complete code of the form processor}

To summarize, here’s the complete source code for the form processing package:

// class formElement
// creates form elements
class formElement{
    private $html=”;
    public function __construct($type=’text’,$attributes=array
(‘name’=>’default’),$options=array()){
        // check for <input> elements
        if(preg_match(“/^
(text|radio|checkbox|password|hidden|submit|reset|button|image|
file)$/”,$type)){
            $openTag='<input type=”‘.$type.'” ‘;
            $closeChar=’ ‘;
            $closeTag=’/>';
        }
        // check for <textarea> and <select> elements
        else if(preg_match(“/^(textarea|select)$/”,$type)){
            $openTag='<‘.$type.’ ‘;
            $closeChar=’>';
            $closeTag='</’.$type.’>';
        }
        else{
            throw new Exception(‘Invalid element type’);
        }
        if(!is_array($attributes)||count($attributes)<1){
            throw new Exception(‘Invalid number of attributes for
<‘.type.’> element’);
        }
        // loop over element attributes
        $elemAttributes=”;
        foreach($attributes as $attribute=>$value){
            if(empty($attribute)||empty($value)){
                throw new Exception(‘Invalid attribute or value
for <‘.type.’> element’);
            }
            // check for ‘required’ attribute – add client-side
validation
            $attribute==’required’?JSGenerator::addValidation
($attributes
['name'],$value):$elemAttributes.=$attribute.’=”‘.$value.'” ‘;
        }
        // check for <select> options
        $selOptions=”;
        if(count($options)>0){
            foreach($options as $value=>$text){
                if(empty($value)||empty($text)){
                    throw new Exception(‘Invalid value or text
for <‘.type.’> element’);
                }
                $selOptions.='<option value=”‘.$value.'”>’.$text.'</option>';
            }
        }
        // build form element(X)HTML output
        $this->html.=$openTag.trim
($elemAttributes).$closeChar.$selOptions.$closeTag;
    }
    // return complete (X)HTML
    public function getHTML(){
        return $this->html;
    }
}
// class JSGenerator
// generates client-side validation functions
abstract class JSGenerator{
    private static $js=array();
    // load external JavaScript validating functions
    public function initializeFunctions(){
        self::$js['ext']='<script language=”javascript”
src=”functions.js”></script>';
    }
    // add JavaScript validating function to selected field
    public function addValidation($fieldName,$valData){
        if(!is_array($valData)){
            throw new Exception(‘Invalid client-side validation
array’);
        }
        $obj=’document.getElementsByTagName(“form”)[0].elements
["'.$fieldName.'"]‘;
        // obtain client-side validating function & error message
        list($valFunction,$errorMessage)=$valData;
        self::$js['int'].=’if
(!’.$valFunction.'(‘.$obj.’,”‘.$errorMessage.'”)){‘.$obj.’.focus
();return false};';
    }
    // return JavaScript code
    public function getCode(){
        return self::$js['ext'].'<script
language=”javascript”>function validate(){‘.self::$js['int'].’}</script>';
    }
}
// class formValidator
// performs server-side form validation
class formValidator{
    private $errors=array();
    public function __construct(){}
    // validate empty field
    public function validateEmpty($field,$errorMessage,$min=4,$max=32){
        if(!isset($_POST[$field])||trim($_POST[$field])
==”||strlen($_POST[$field])<$min||strlen($_POST[$field])>$max){
            $this->errors[]=$errorMessage;
        }
    }
    // validate integer field
    public function validateInt($field,$errorMessage){
        if(!isset($_POST[$field])||!is_numeric($_POST[$field])
||intval($_POST[$field])!=$_POST[$field]){
            $this->errors[]=$errorMessage;
        }
    }
    // validate numeric field
    public function validateNumber($field,$errorMessage){
        if(!isset($_POST[$field])||!is_numeric($_POST[$field])){
            $this->errors[]=$errorMessage;
        }
    }
    // validate if field is within a range
    public function validateRange($field,$errorMessage,$min=1,$max=99){
        if(!isset($_POST[$field])||$_POST[$field]<$min||$_POST
[$field]>$max){
            $this->errors[]=$errorMessage;
        }
    }
    // validate alphabetic field
    public function validateAlphabetic($field,$errorMessage){
        if(!isset($_POST[$field])||!preg_match(“/^[a-zA-Z]
+$/”,$_POST[$field])){
            $this->errors[]=$errorMessage;
        }
    }
    // validate alphanumeric field
    public function validateAlphanum($field,$errorMessage){
        if(!isset($_POST[$field])||!preg_match(“/^[a-zA-Z0-9]
+$/”,$_POST[$field])){
            $this->errors[]=$errorMessage;
        }
    }
    // validate email
    public function validateEmail($field,$errorMessage){
        if(!isset($_POST[$field])||!preg_match
(“/.+@.+..+./”,$_POST[$field])||!checkdnsrr(array_pop(explode
(“@”,$_POST[$field])),”MX”)){
            $this->errors[]=$errorMessage;
        }
    }
    // private method ‘windnsrr()’ for Windows systems
    private function windnsrr($hostName,$recType=”){
        if(!empty($hostName)){
            if($recType==”)$recType=”MX”;
            exec(“nslookup -type=$recType $hostName”,$result);
            foreach($result as $line){
                if(preg_match(“/^$hostName/”,$line)){
                    return true;
                }
            }
            return false;
        }
        return false;
    }
    // check for errors
    public function checkErrors(){
        if(count($this->errors)>0){
            return true;
        }
        return false;
    }
    // return errors
    public function displayErrors(){
        $errorOutput='<ul>';
        foreach($this->errors as $err){
            $errorOutput.='<li>’.$err.'</li>';
        }
        $errorOutput.='</ul>';
        return $errorOutput;
    }
}
// class formGenerator
// builds up the web form
class formGenerator{
    private $html=array();
    private $action;
    private $method;
    public function __construct($action=”,$method=’post’){
        // setup form attributes
        $this->action=empty($action)?$_SERVER
['PHP_SELF']:$action;
        $this->method=$method!=’post’||$method!
=’get’?’post':$method;
    }
    // add form element
    public function addElement($type=’text’,$attributes=array
(‘name’=>’default’),$options=array()){
        if(!$elem=new formElement($type,$attributes,$options)){
            throw new Exception(‘Failed to instantiate ‘.$type.’
object’);
        }
        $this->html[]=$elem->getHTML();
    }
    // add form part
    public function addFormPart($formPart='<br />’){
        $this->html[]=trim($formPart)==”?'<br />':$formPart;
    }
    // display form
    public function display(){
        $formOutput='<form action=”‘.$this->action.'”
method=”‘.$this->method.'”>';
        foreach($this->html as $html){
            $formOutput.=$html;
        }
        $formOutput.='</form>';
        // load global JavaScript checking functions
        JSGenerator::initializeFunctions();
        // append JavaScript code to general (X)HTML output
        $formOutput.=JSGenerator::getCode();
        return $formOutput;
    }
}

Wrapping up

In this article, I went through the makings of an extensible form processing library, for use either in PHP 5, or –- with minor modifications — in PHP 4. If you’re serious about taking PHP to more complex levels of development, I encourage you to grab the proper theory behind processing forms through the object-oriented paradigm, and then make your own way, either by extending the package I developed or by picking up an existing one. As always, the choice is up to you. Meet you in the next PHP tutorial!

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan