Welcome Guest, Not a member yet? Register   Sign In
How to add your own custom errors to the form validation class
#1

[eluser]diez[/eluser]
Recently I've had the need to add custom form errors while using the form validation class. I know I can create a callback function within the set_rule() method. However, during certain situations this caused me to make duplicate database calls.

Here's how you would use the add_custom_error() function:

Controller
Code:
$this->load->library('form_validation');
    
if ($this->input->post('email') != $user_email_from_database)
{
    $this->form_validation->add_custom_error('email_field', "The email entered is not registered as an account.");  
}

if ($this->form_validation->run() == FALSE)
{    
     $this->load->view('login/login_view');
}

View
Code:
<html>

.......

<?php echo validation_errors(); ?> <!-- will display both native and custom errors-->

<h1>New User</h1>

&lt;?php echo form_open('login'); ?&gt;

<h5>Email Address</h5>
&lt;?php echo form_error('email'); ?&gt; &lt;!-- will display both native and custom errors--&gt;
&lt;input type="text" name="email" value="&lt;?php echo set_value('email'); ?&gt;" size="50" /&gt;

.......

<div>&lt;input type="submit" value="Submit" /&gt;&lt;/div>

&lt;/form&gt;

.......

&lt;/html&gt;


NOTE:

There are 2 ways of outputting the errors.

you can use:

Code:
1.) echo form_error('email'); &lt;!-- will display individual error msg associated with the form field  --&gt;

2.) echo validation_errors(); &lt;!-- will display all form error msgs as a batch --&gt;


native errors will be displayed first (if there are any) then, custom errors will be displayed in second priority.



If you want to use the add_custom_error() function extending the form validation class in CI, you can implement the following:

1.) Download the MY_Form_validation.php attachment and save it in your application/library folder


The only code added in the extended class is the following:

Code:
//***class variable we define at the top of our extended class

var $custom_field_errors = array(); //array that hold fields from errors



//***new function

function add_custom_error($field = '', $error_message = '')
{
    if($field == '')
    {
       return '';
    }
    $this->custom_field_errors[$field]  = $error_message;
    
    return true;
}



//***code snippet that is added into the run() method that we extend

//insert custom errors into native form validation error arrays
if(count($this->custom_field_errors) > 0)
{
    foreach($this->custom_field_errors as $field => $error_message)
    {
        $this->_error_array[$field] = $error_message;
        $this->_field_data[$field]['error'] = $error_message;
    }
}
#2

[eluser]diez[/eluser]
For some reason, i wasn't allowed to upload the class as a php or txt file - So i'll just paste the code below

create a new file called "MY_Form_validation.php" and save it in your application/library folder

Code:
&lt;?php
class MY_Form_validation extends CI_Form_validation
{
    
    var $custom_field_errors = array(); //array that hold fields from errors
    
    function MY_Form_validation()
    {
        parent::CI_Form_validation();
        $CI =& get_instance();
        $CI->load->model(array('user_model'));  
      
    }

    /**
    * put your comment there...
    *
    * @param string $field
    * @param string $error_message
    * @return mixed
    */
    function add_custom_error($field = '', $error_message = '')
    {
        if($field == '')
        {
           return '';
        }
        $this->custom_field_errors[$field]  = $error_message;
        
        return true;
    }
    
    
    /**
    * adds customer form error
    *
    * @param string $str_field
    * @param string $str_message
    */
    function has_custom_errors()
    {
        if($field == '')
        {
            return '';
        }

        if(count($this->custom_field_errors) > 0)
        {
           return false;
        }
        
        return true;
    }
    
    function run($group = '')
    {
        // Do we even have any data to process?  Mm?
        if (count($_POST) == 0)
        {
            return FALSE;
        }
        
        // Does the _field_data array containing the validation rules exist?
        // If not, we look to see if they were assigned via a config file
        if (count($this->_field_data) == 0)
        {
            // No validation rules?  We're done...
            if (count($this->_config_rules) == 0)
            {
                return FALSE;
            }
            
            // Is there a validation rule for the particular URI being accessed?
            $uri = ($group == '') ? trim($this->CI->uri->ruri_string(), '/') : $group;
            
            if ($uri != '' AND isset($this->_config_rules[$uri]))
            {
                $this->set_rules($this->_config_rules[$uri]);
            }
            else
            {
                $this->set_rules($this->_config_rules);
            }
    
            // We're we able to set the rules correctly?
            if (count($this->_field_data) == 0)
            {
                log_message('debug', "Unable to find validation rules");
                return FALSE;
            }
        }
    
        // Load the language file containing error messages
        $this->CI->lang->load('form_validation');
                            
        // Cycle through the rules for each field, match the
        // corresponding $_POST item and test for errors
        foreach ($this->_field_data as $field => $row)
        {        
            // Fetch the data from the corresponding $_POST array and cache it in the _field_data array.
            // Depending on whether the field name is an array or a string will determine where we get it from.
            
            if ($row['is_array'] == TRUE)
            {
                $this->_field_data[$field]['postdata'] = $this->_reduce_array($_POST, $row['keys']);
            }
            else
            {
                if (isset($_POST[$field]) AND $_POST[$field] != "")
                {
                    $this->_field_data[$field]['postdata'] = $_POST[$field];
                }
            }
        
            $this->_execute($row, explode('|', $row['rules']), $this->_field_data[$field]['postdata']);        
        }
        
        //insert custom errors into native form validation error arrays
        if(count($this->custom_field_errors) > 0)
        {
            foreach($this->custom_field_errors as $field => $error_message)
            {
                $this->_error_array[$field] = $error_message;
                $this->_field_data[$field]['error'] = $error_message;
            }
        }
        
        // Did we end up with any errors?
        $total_errors = count($this->_error_array);

        if ($total_errors > 0)
        {
            $this->_safe_form_data = TRUE;
        }

        // Now we need to re-set the POST data with the new, processed data
        $this->_reset_post_array();
      
        // No errors, validation passes!
        if ($total_errors == 0)
        {
            return TRUE;
        }

        // Validation fails
        return FALSE;
    }
}


    

?&gt;
#3

[eluser]Spir[/eluser]
You should call your constructor __construct to be compliant with CI 2.0
I don't know if your code is for CI 2.0 but here is a quicker way to make it :
Code:
&lt;?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class MY_Form_validation extends CI_Form_validation
{
    function __construct()
    {
        parent::__construct();
    }

   function set_errors($fields)
   {
           if (is_array($fields) and count($fields))
           {
               foreach($fields as $key => $val)
               {
                   if ( array_key_exists($key, $this->_field_data) AND $this->_field_data[$key]['error']!='' AND $this->_error_array[$key] != '' ) {
                       $this->_field_data[$key]['error'] = $val;
                       $this->_error_array[$key] = $val;
                   }
            }
        }
    }
}

Since form validation store the field you set using set_rules in an array called '_field_data'. Error are also stored there when they exists. And there is a specific error array for all erro which is used when you call
Code:
echo validation_errors();

So in your controller you can set it this way :
Code:
if ($this->form_validation->run() == FALSE){
    $this->form_validation->set_errors(array('email' => 'Your email is not valid'));
    ...
For example.
#4

[eluser]Rein Van Oyen[/eluser]
This is very interesting stuff. Alltough, could it be possible to use this without having to fill in a inputfield as first parameter to the add_custom_error method? For instance when you're using a authentication-function which checks both the username and password and want to keep the validation errors on both inputfields.

Rein
#5

[eluser]Spir[/eluser]
[quote author="Rein Van Oyen" date="1297103871"]This is very interesting stuff. Alltough, could it be possible to use this without having to fill in a inputfield as first parameter to the add_custom_error method? For instance when you're using a authentication-function which checks both the username and password and want to keep the validation errors on both inputfields.

Rein[/quote]Using my code if you do :
Code:
&lt;?php echo form_error('your_field'); ?&gt;
You should get your custom error message.
#6

[eluser]Rein Van Oyen[/eluser]
Spir, thanks for your quick reply.

The problem however is that I'm showing my errors in my header template, which is used throughout the whole application. My goal is to use the form validation together with my own error messages which are not only showing up for formvalidation purposes.
#7

[eluser]Spir[/eluser]
[quote author="Rein Van Oyen" date="1297105017"]Spir, thanks for your quick reply.

The problem however is that I'm showing my errors in my header template, which is used throughout the whole application. My goal is to use the form validation together with my own error messages which are not only showing up for formvalidation purposes.[/quote]Then you should autoload form_validation.
Then you'll be able to see if there are error :

Code:
if (count($this->form_validation->_error_array)){
    // here you can loop on error
    foreach($this->form_validation->_error_array) as $key => $error){
        echo $error;
    }
}
or something similar. I didn't test this.
#8

[eluser]Rein Van Oyen[/eluser]
Thank you Spir, I'll extend the class by adding a new method called display_custom_errors or something like that. Smile
#9

[eluser]diez[/eluser]
NOTE:

There are 2 ways of outputting the errors.

you can use:

Code:
1.) echo form_error('email'); &lt;!-- will display individual error msg associated with the form field  --&gt;

2.) echo validation_errors(); &lt;!-- will display all form error msgs as a batch --&gt;


native errors will be displayed first (if there are any) then, custom errors will be displayed in second priority.




Theme © iAndrew 2016 - Forum software by © MyBB