Skip to content

ClientServer Validation

World Wide Web Server edited this page Jul 4, 2012 · 13 revisions

Category:Validation Category:Libraries Category:Libraries::Validation Category:Libraries::Core Extensions

Implementing client-side and server-side validation usually requires a significant duplication of effort. Despite following the same logic rules, the code usually must be developed in two different environments - e.g. javascript and php.

For those who are too lazy to do the same work twice (like I am), here is a crude prototype of a validation library (subclass of built-in Validation class) that would do this work for you.

The usage is simple:

  1. Add a method to your controller, where you set up your validation rules.
  2. Call this method twice per form life-cycle: once before rendering the form (html), and again after it has been submitted.

For example:

  1. Set up validation: [code] function _setup_validation() { $this->load->library('validation');

     $fields = array(
         'email'=>'Email',
         'password'=>'Password',
         'password2'=>'Confirm Password',
         'firstname' => 'First Name',
         'lastname' => 'Last Name',
         'address1'=>'Address 1',
         'city'=>'City',
         'zipcode'=>'Zip'
     );
     
     $rules = array(
         'email'=>'required|valid_email',
         'password'=>'min_length[5]',
         'password2'=>'required|matches[password]',
         'firstname' => 'required',
         'lastname' => 'required',
         'address1'=>'required',
         'city'=>'min_length[2]',
         'zipcode'=>'exact_length[5]'
     );
     
     $this->validation->set_fields($fields);
     $this->validation->set_rules($rules);
    

    } [/code]

  2. When rendering the form, define your validation rules and then call special function from our Validation (sub)class to generate a corresponding [removed]

[code] function index() { $this->_setup_validation();

    $data['javascript'] = $this->validation->javascript();
    $this->load->view('register', $data);
}

[/code]

  1. In your view, use 'javascript' variable to inject the contents of our validation (js) script:

[code] <html> <head> <title>Account Registration</title> <?= @$javascript ?> </head> ... [/code]

  1. Once the form has been submitted, process it as usual:

[code] function submit() { $this->_setup_validation();

    if ($this->validation->run() == false)
        return $this->index();

    $this->load->view('sucess');
}

[/code]

Here's [b]MY_Validation.php[/b] in its entirety:

[code] <?php if (!defined('BASEPATH')) exit('No direct script access allowed');

// ------------------------------------------------------------------------

/**

  • Validation Class extension

  • @package CodeIgniter

  • @subpackage Libraries

  • @category Validation

  • @author AK

  • @link http://codeigniter.com/user_guide/libraries/validation.html */

    /**

    • Set Fields
    • This function takes an array of field names as input
    • and generates class variables with the same name, which will
    • either be blank or contain the $_POST value corresponding to it
    • @access public
    • @param string
    • @param string
    • @return void */ class MY_Validation extends CI_Validation {

    function MY_Validation() { parent::CI_Validation(); }

    /**

    • JavaScript
    • This function provides default implementation of the built-in CI validation rules in javascript.
    • The function generates a client-side js script, complete with ... html tags,
    • suitable for inclusion in the document header. Additionally, custom rules can be added by
    • defining global js functions, or extending Validation js object.
    • @access public
    • @param string
    • @param string
    • @return void */

    function javascript($alert_msg='', $alert_func='null') { if(!$this->_fields || !$this->_rules) return 'function validation_run(f) {}';

     // client-side javascript implementation of CI built-in validation rules.
     $script = '
    

String.prototype.trim = function() { return this.replace(/^\s\s*/, "").replace(/\s\s*$/, ""); } var Validator = function(f) { this.form = f; } Validator.prototype.required = function(str) { return str.search(/\S/) > -1; } Validator.prototype.matches = function(str, field) { return (str == this.form.elements[field].value); } // FIX! change "field" from input name to input ref?

Validator.prototype.max_length = function(str, val) { return (str.length <= val); } Validator.prototype.min_length = function(str, val) { return (str.length >= val); } Validator.prototype.exact_length = function(str, val) { return (str.length == val); } Validator.prototype.valid_email = function(str) { return str.search(/^([\w+-]+)(.[\w+-]+)*@([a-z\d-]+.)+[a-z]{2,6}$/i) > -1; } Validator.prototype.valid_ip = function(ip) { var segments = ip.split("."); for (var i in segs) if(segs[i].length>3 || segs[i]>255 || segs[i].search(/\D/)>-1) return false; return true; } Validator.prototype.alpha = function(str) { return str.search(/[^a-z]/i) == -1; } Validator.prototype.alpha_numeric = function(str) { return str.search(/[^a-z0-9]/i) == -1; } Validator.prototype.alpha_dash = function(str) { return str.search(/[^\w-]/i) == -1; } Validator.prototype.numeric = function(str) { return ! isNaN(str); } Validator.prototype.integer = function(str) { return ! (isNaN(str) || str.indexOf(".") > -1); } Validator.prototype.valid_base64 = function(str) { return str.search(/[^a-zA-Z0-9/+=]/) == -1; } Validator.prototype.validate = function (rules, callback) { try { if (!rules.length) return true;
var res, errors=[]; for (var i in rules) { var item = rules[i]; var field = this.form.elements[item.input];
var rule_list = item.rule.split("|");

    for (var r in rule_list) {
        var re = /(callback_|validate_)?(\w+)(?:\[(.+)\])?/i.exec&#40;rule_list[r]&#41;;
        var func = re[2];
        //if (!re[1]) re[1] = "";
        if (!this[func]) {
            try { func = eval&#40;func&#41;; } catch (e2) { } 
            res = (typeof(func) == "function") ? func(field.value, re[3]) : false;
        } else {
            res = this[func](field.value, re[3]);
        }
    }
    if (!res && item.msg) {
        errors.push([item.msg, item.input]);
    }
} } catch (e) { alert&#40;e&#41;; }    
if (errors.length) {
    // show errors
    return callback ? callback(errors) : display_alert&#40;errors&#41;;
}
return true;

} '; // default alert message if ($alert_msg == '') $alert_msg = 'Please fix the following errors:';

    // default implementation of the validation action
    $script .= '

function display_alert(errors) { var str = ""; for (var i in errors) str += "\n- " + errors[i][0]; alert("'. addslashes($alert_msg) .'" + str); return false; } '; // Load the language file containing error messages $this->CI->lang->load('validation');

    $params = null;

    foreach ($this->_rules as $field => $rules)
    {        
        //Explode out the rules!
        $ex = explode('|', $rules);
        $messages = array();
        
        foreach ($ex as $rule)
        {
            $param = FALSE;
            if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match))
            {
                $rule    = $match[1];
                $param    = $match[2];
            }
            
            if ( ! isset($this->_error_messages[$rule]))
            {
                if (FALSE === ($line = $this->CI->lang->line($rule)))
                {
                    $line = 'Unable to access an error message corresponding to your field name.';
                }                        
            }
            else
            {
                $line = $this->_error_messages[$rule];
            }
            
            // Build the error message
            $mfield = ( ! isset($this->_fields[$field])) ? $field : $this->_fields[$field];
            $mparam = ( ! isset($this->_fields[$param])) ? $param : $this->_fields[$param];
            $messages[] = sprintf($line, $mfield, $mparam);
        }
        

                
        $params[] = '{input:"'.$field.'",rule:"'.$rules.'",name:"'
                .( isset($this->_fields[$field]) ? addslashes($this->_fields[$field]) : $field ).'",msg:"'.join(' ', $messages).'"}';
    }
    
    $script .= "\nfunction validation_run(f) {\n\tvar rules = [\n\t\t" . join(",\n\t\t", $params) . "\n\t];\n\treturn new Validator(f).validate(rules,". $alert_func .");\n}\n";

    return $script;
}

}

?> [/code]

Clone this wiki locally