View Single Post
Old 12-03-2005, 06:12 PM   PM User | #1
marek_mar
Sensei


 
Join Date: Aug 2003
Location: One step ahead of you.
Posts: 2,815
Thanks: 0
Thanked 3 Times in 3 Posts
marek_mar is on a distinguished road
Simple form builder/validator.

I've written this simple class as a part of a project I've been doing. It required lots of forms so I quickly saw a need for it.
PHP Code:
class form
{
    var 
$name '';
    var 
$action '';
    var 
$data = array();
    var 
$error = array();
    var 
$valid = array();
    var 
$submit = array();

    function 
form($name$action)
    {
        
$this->name $name;
        
$this->action $action;
        return 
true;
    }

    function 
add($name$type$human_value$value false$max false$min false$size false)
    {
        if(isset(
$this->data[$name]))
        {
            return -
1;
        }
        if(
$type == 'submit')
        {
            
$this->submit[] = $name;
        }
        if(!
$type != 'select')
        {
            
$this->data[$name] = array_slice(func_get_args(), 1);
            return 
true;
        }
        
$this->data[$name] = array(func_get_arg(1), array_slice(func_get_args(), 1));
        return 
true;
    }

    function 
add_option($select$value$human_value false)
    {
        if(!isset(
$this->data[$select]) || ($this->data[$select][0] != 'select' && $this->data[$select][0] != 'radio'))
        {
            return 
false;
        }
        
$this->data[$select][] = array_slice(func_get_args(), 1);
        return 
true;
    }

    function 
raw($data)
    {
        
$this->data[] = array('raw'$data);
        return 
true;
    }

    function 
check_submit()
    {
        for(
$i 0$n count($this->submit); $i $n$i++)
        {
            if(isset(
$_POST[$this->submit[$i]]))
            {
                return 
$this->submit[$i];
                break;
            }
        }
        return 
false;
    }

    function 
get_valid_values()
    {
        
$ret = array();
        for(
$i 0$n count($this->valid); $i $n $i++)
        {
            if(
$this->data[$this->valid[$i]][0] == 'select' || $this->data[$this->valid[$i]][0] == 'radio')
            {
                
$ret[$this->valid[$i]] = $this->data[$this->valid[$i]][$_POST[$this->valid[$i]] + 1][0];
            }
            else
            {
                
$ret[$this->valid[$i]] = $_POST[$this->valid[$i]];
            }
        }
        return 
$ret;
    }

    function 
make($show_errors true)
    {
        
$ret = array();
        
$submit $this->check_submit();
        
$i 1;
        
$ret[] = '<form name="' $this->name '" action="' $this->action '" method="POST">';
        foreach(
$this->data as $name => $values)
        {
            
$ret[$i] = (strlen($values[1]) && $values[0] != 'raw') ? '<label for="' $name '">' $values[1] . ': </label>' '';
            switch(
$values[0])
            {
                case 
'raw':
                    
$ret[$i] = $values[1];
                break;
                case 
'textarea':
                    
$ret[$i] .= '<br /><textarea name="' $name '" id="' $name '"' . ((isset($values[5]) && is_array($values[5])) ? 'cols="' $values[5][0] . '" rows="' $values[5][1] . '"' '') . '>' . (($submit && isset($_POST[$name])) ? $_POST[$name] : $values[2]) . '</textarea>';
                    
$ret[$i] .= ($show_errors && isset($this->error[$name])) ? "<br />\n{$this->error[$name]}\n" '';
                break;
                case 
'select':
                    
$ret[$i] .= '<select name="' $name '" id="' $name '">' "\n";
                    for(
$j 2$m count($values); $j $m$j++)
                    {
                        
$ret[$i] .= '<option value="' . ($j 1) . '"' . ((isset($_REQUEST[$name]) && ($_REQUEST[$name] == ($j 1))) ? ' selected="selected"' '') . '>' . (isset($values[$j][1]) ? $values[$j][1] : $values[$j][0]) . '</option>' "\n";
                    }
                    
$ret[$i] .= '</select>';
                    
$ret[$i] .= ($show_errors && isset($this->error[$name])) ? "<br />\n{$this->error[$name]}\n" '';
                break;
                case 
'radio':
                    for(
$j 2$m count($values); $j $m$j++)
                    {
                        
$ret[$i] .= '<input type="radio" name="' $name '" id="' $name . ($j 1) . '"' ' value="' . ($j 1) . '"' . ((isset($_POST[$name]) && ($_POST[$name] == ($j 1))) ? ' checked="checked"' '') . '/><label for="' $name . ($j 1) . '">' . (isset($values[$j][1]) ? $values[$j][1] : $values[$j][0]) . "</lable>\n";
                    }
                break;
                case 
'checkbox':
                    
$ret[$i] = '<input type="checkbox" name="' $name '" id="' $name '"' ' value="1"' . ((isset($_POST[$name]) && $_POST[$name]) ? ' checked="checked"' '') . '/><label for="' $name '">' . (isset($values[1]) ? $values[1] : $values[0]) . "</lable>\n";
                    
$ret[$i] .= ($show_errors && isset($this->error[$name])) ? "<br />\n{$this->error[$name]}\n" '';
                break;
                case 
'number':
                case 
'email':
                    
$ret[$i] .= '<input type="text" name="' $name '" id="' $name '"' . (((isset($values[2]) && $values[2]) || $submit) ? ' value="' . (($submit && isset($_POST[$name])) ? $_POST[$name] : $values[2]) . '"' '') . ((isset($values[5]) && $values[5]) ? ' size="' $values[5] . '"' '') . ((isset($values[3]) && $values[3]) ? ' maxlength="' . (($values[0] == 'number') ? strlen($values[3]) : $values[3]) . '"' '') . '/>';
                    
$ret[$i] .= ($show_errors && isset($this->error[$name])) ? "<br />\n{$this->error[$name]}\n" '';
                break;
                case 
'submit':
                    
$ret[$i] = '<input type="submit" name="' $name '" value="' $values[1] . '"/>';
                break;
                default:
                    
$ret[$i] .= '<input type="' $values[0] . '" name="' $name '" id="' $name '"' . (((isset($values[2]) && $values[2]) || $submit) ? ' value="' . (($submit && isset($_POST[$name])) ? $_POST[$name] : $values[2]) . '"' '') . ((isset($values[5]) && $values[5]) ? ' size="' $values[5] . '"' '') . ((isset($values[3]) && $values[3]) ? ' maxlength="' $values[3] . '"' '') . '/>';
                    
$ret[$i] .= ($show_errors && isset($this->error[$name])) ? "<br />\n{$this->error[$name]}\n" '';
                break;
            }
            
$i++;
            
$ret[] = '</form>';
        }
        return 
$ret;
    }

    function 
validate($filled false)
    {
        foreach(
$this->data as $name => $values)
        {
            if(!isset(
$_POST[$name]))
            {
                
$_POST[$name] = '';
            }

            
$_POST[$name] = trim($_POST[$name]);
            
$_POST[$name] = (get_magic_quotes_gpc()) ? stripslashes($_POST[$name]) : $_POST[$name];

            if(
is_array($filled) && in_array($name$filled) && !strlen($_POST[$name]))
            {
                
$this->error[$name] = 'Value must be set.';
                continue;
            }
            switch(
$values[0])
            {
                case 
'raw':
                break;
                case 
'number':
                    if(!
is_numeric($_POST[$name]))
                    {
                        
$this->error[$name] = 'Value must be a number.';
                    }
                    if((isset(
$values[3]) && $values[3] !== false && (float) $_POST[$name] > (float) $values[3]) || (isset($values[4]) && $values[4] !== false && (float) $_POST[$name] < (float) $values[4]))
                    {
                        
$this->error[$name] = 'Value is too big/small. Value should be between ' . ((isset($values[4])) ? $values[4] : '0') . ' and ' $values[3] . '.';
                    }
                break;
                case 
'select':
                case 
'radio':
                    if(!
is_numeric($_POST[$name]))
                    {
                        
$this->error[$name] = 'Unpredicted value.';
                    }
                break;
                case 
'email':
                    if(!
preg_match('/^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/'$_POST[$name]))
                    {
                        
$this->error[$name] = 'Value is not an email address.';
                    }
                break;
                default:
                    if((isset(
$values[3]) && $values[3] !== false && strlen($_POST[$name]) >= $values[3]) || (isset($values[4]) && $values[4] !== false && strlen($_POST[$name]) <= $values[4]))
                    {
                        
$this->error[$name] = 'Value is too long/short. Value should be between ' . ((isset($values[4])) ? $values[4] : '0') . ' and ' $values[3] . ' characters long.';
                    }
                break;
            }
            if(!isset(
$this->error[$name]))
            {
                
$this->valid[] = $name;
            }
        }
        if(
count($this->error))
        {
            return 
$this->error;
        }
        return 
true;
    }

Ok that's the class and now how to use it:
PHP Code:
$form = new form('form name''file the form should submit to'); 
Both arguments are required for the constructor.
It returns true.

To add a form element you use the add() method.
PHP Code:
$form->add('elenent name''element type''description''default value'/* maximum length */ 10/* minimum length */ 0/* size */ 10); 
Arguments after "description" are optional. The last three should be either int or float. If the type is "textarea" the $size argument should be a two element array (width, height).
The types are: text, password, textarea, radio, checkbox, select, number*, email and submit.
It returns bool(true) or int(-1) if an element with the same name exists.

To add options to the select or radio element you use the add_option() method.
PHP Code:
$form->add_option('name of the select element to which this option belongs''the returned value''the value presented to the user'); 
The last argument is optional. The value of the 2nd argument will be used if it is not set.
It returns bool(true) or bool(false) if there is no select element with the given name.

The make() method returns an array with the form. It return an array so you can add whatever you like inbetween the fields.
PHP Code:
$form->make(/* show errors */ true); 
The argument is optional and defaults to true. It will print errors below the form elemnts that were filled in incorrectly.

The validate() method validates the form.
PHP Code:
$form->validate(array('these''are''the''names''of elemnts''that''must be''filled in')); 
The argument is optional. It must be an array.
It returns bool(true) or an array with all the errors.

The check_submit() method checks if a form has been submited.
PHP Code:
if(false !== $form->check_submit())
{
   print 
'Form was submitted';

It returns the name of the submit button user or false.

The get_valid_values() method returns an associative array with all the values that passed the validation.
PHP Code:
var_dump($form->get_valid_values()); 
To add something between the form elements and not have to play with the array returned by form::make() you can add some raw HTML with the raw() method.
PHP Code:
$form->raw('Some HTML'); 
An example:
PHP Code:
$form = new form('upload'$_SERVER['PHP_SELF']);
$form->add('filename''text''Name'false100);
$form->add('comment''textarea''Comments''Put comments here'102, array(10020));
$form->add('guess''number''Guess a numer from 1 to 10'false1012);
$form->add('order''select''Sort order');
$form->raw('Hello there!<br>');
$form->add_option('order''ASC''Ascending');
$form->add_option('order''DESC''Descending');
$form->add('email''email''eMail'false100);
$form->add('choice''radio''Are you sure?');
$form->add_option('choice''he is stupid''No');
$form->add_option('choice''he is smart''Yes');
$form->add('agreement''checkbox''I agree to be good');
$form->add('submit''submit''Upload');
if(
$form->check_submit())
{
    if(
true === $form->validate(array('filename''agreement')))
    {
        print 
'Form is filled out correctly.';
    }
}
print 
implode("<br />\n"$form->make());
var_dump($form->get_valid_values()); 
I may update this if needed.

NOTES:
It does not support arrays (element names with []). Then again it might... to some extent... It was not needed.

*The number type is validated by the size of the number not by the length.
__________________
I'm not sure if this was any help, but I hope it didn't make you stupider.

Experience is something you get just after you really need it.
PHP Installation Guide Feedback welcome.

Last edited by marek_mar; 12-08-2005 at 04:10 PM..
marek_mar is offline   Reply With Quote