Welcome Guest, Not a member yet? Register   Sign In
Custom Validation Rules in Extended Form Validation Library
#1

[eluser]Unknown[/eluser]
I'm hoping to find some help extending the Form Validation Library to make use of some custom validation rules I've created and used as callback functions in my Controllers.

Since there are now several that are used throughout multiple controllers I was hoping to only have to keep them in once place.

Has anyone had any luck with this?
#2

[eluser]CroNiX[/eluser]
Sure.

/application/libraries/MY_Form_validation.php (must be named this, and located in libraries. It will be loaded automatically whenever you load the form_validation library normally)
Code:
class MY_Form_validation extends CI_Form_validation {

    function __construct($rules = array())
    {
        parent::__construct($rules);
    }

    //create your custom rules

    public function newrule($field_value) //$field_value = value passed from form field
    {
        //do the test on the field value
        if ($field_value !== 'heya')
        {
            //set the error message to the name of this rule and provide the message. %s will be replaced with the field name
            $this->set_message('newrule', 'The %s field can only be "heya"');

            //return false as we failed
            return FALSE;
        }

        //Rule passed, return TRUE
        return TRUE;
    }
}

Then in controller, use like normal rules:
Code:
$this->form_validation->set_rules('name', 'Name',  'trim|newrule'); //no callback_ prefix...

If the rule failed, the message would be:
The name field can only be "heya"
#3

[eluser]Unknown[/eluser]
CroNiX,
That's what I had thought, but it would appear that if the fields are not given a value, that the custom validation rule isn't being run.

I've set up a bare-bones demo using the following:

My Controller: welcome.php
Code:
class Welcome extends CI_Controller
{
public function __construct()
{
  parent::__construct();
  $this->load->library('form_validation');
  $this->load->helper('form');
  $this->form_validation->set_error_delimiters('<span class="help-block"><span class="text-error">', '</span></span>');
}

public function index()
{
  if ($this->form_validation->run('welcome') == FALSE)
  {
   $this->load->view('welcome_message');
  }
  else
  {
   echo '<pre>';
   print_r($this->input->post());
   echo '</pre>';
  }
}
}

My View: welcome_message.php
Code:
&lt;? $attributes = array('class' => 'test form-horizontal', 'id' => 'test-form'); ?&gt;<!DOCTYPE html>
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="utf-8"&gt;
&lt;title&gt;Welcome to CodeIgniter&lt;/title&gt;

&lt;style type="text/css"&gt;

::selection{ background-color: #E13300; color: white; }
::moz-selection{ background-color: #E13300; color: white; }
::webkit-selection{ background-color: #E13300; color: white; }

body {
  background-color: #fff;
  margin: 40px;
  font: 13px/20px normal Helvetica, Arial, sans-serif;
  color: #4F5155;
}

a {
  color: #003399;
  background-color: transparent;
  font-weight: normal;
}

h1 {
  color: #444;
  background-color: transparent;
  border-bottom: 1px solid #D0D0D0;
  font-size: 19px;
  font-weight: normal;
  margin: 0 0 14px 0;
  padding: 14px 15px 10px 15px;
}

code {
  font-family: Consolas, Monaco, Courier New, Courier, monospace;
  font-size: 12px;
  background-color: #f9f9f9;
  border: 1px solid #D0D0D0;
  color: #002166;
  display: block;
  margin: 14px 0 14px 0;
  padding: 12px 10px 12px 10px;
}

#body{
  margin: 0 15px 0 15px;
}

p.footer{
  text-align: right;
  font-size: 11px;
  border-top: 1px solid #D0D0D0;
  line-height: 32px;
  padding: 0 10px 0 10px;
  margin: 20px 0 0 0;
}

#container{
  margin: 10px;
  border: 1px solid #D0D0D0;
  -webkit-box-shadow: 0 0 8px #D0D0D0;
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

<div id="container">
<h1>Welcome to CodeIgniter!</h1>

<div id="body">
  &lt;?=form_open($this->uri->uri_string(), $attributes);?&gt;
  
   <fieldset>
    <legend>A Test Form</legend>
    
    <div class="control-group">
     <label class="control-label" for="red-input">Red</label>
     <div class="controls">
      &lt;input type="text" class="text-input" id="red-input" name="red" maxlength="255" value="&lt;?=set_value('red');?&gt;" placeholder="Red"&gt;
      &lt;?=form_error('red');?&gt;
      
     </div>
    </div>
    
    <div class="control-group">
     <label class="control-label" for="green-input">Green</label>
     <div class="controls">
      &lt;input type="text" class="text-input" id="green-input" name="green" maxlength="255" value="&lt;?=set_value('green');?&gt;" placeholder="Green"&gt;
      &lt;?=form_error('green');?&gt;
      
     </div>
    </div>
    
    <div class="control-group">
     <label class="control-label" for="blue-input">Blue</label>
     <div class="controls">
      &lt;input type="text" class="text-input" id="blue-input" name="blue" maxlength="255" value="&lt;?=set_value('blue');?&gt;" placeholder="Blue"&gt;
      &lt;?=form_error('blue');?&gt;
      
     </div>
    </div>
    
    <div class="control-group">
     <div class="controls">
      <button type="submit" name="submit" value="Submit">Submit</button>
      &lt;?=form_error('submit');?&gt;
      
     </div>
    </div>
   </fieldset>
  &lt;/form&gt;
</div>

<p class="footer">Page rendered in <strong>{elapsed_time}</strong> seconds</p>
</div>

&lt;/body&gt;
&lt;/html&gt;

My Library: MY_Form_validation.php
Code:
class MY_Form_validation extends CI_Form_validation
{
  function __construct($rules = array())
  {
   parent::__construct($rules);
  }
  
  // -------------------------------------------------------------------
  
  /**
  * Require a field's value to be "heya"
  *
  * @access public
  * @param string
  * @return bool
  */
  public function newrule($field_value)
  {
   //do the test on the field value
   if ($field_value !== 'heya')
   {
    //set the error message to the name of this rule and provide the message. %s will be replaced with the field name
    $this->set_message('newrule', 'The %s field can only be "heya"');
    
    //return false as we failed
    return FALSE;
   }
  
   //Rule passed, return TRUE
   return TRUE;
  }
  
  // -------------------------------------------------------------------
  
  /**
  * Require a field if another field is left blank
  *
  * @access public
  * @param string
  * @return bool
  */
  
  public function my_rule($field_value)
  {
   $this->set_message('my_rule', 'This is an error message for the "my_rule" rule.');
   return FALSE;
  }
}

My Validation File: form_validation.php
Code:
$config = array
(
  'welcome' => array
  (
   array
   (
    'field' => 'red',
    'label' => 'Red',
    'rules' => 'trim|my_rule'
   ),
   array
   (
    'field' => 'blue',
    'label' => 'Blue',
    'rules' => 'trim|newrule'
   ),
   array
   (
    'field' => 'green',
    'label' => 'Green',
    'rules' => 'trim|required'
   ),
   array
   (
    'field' => 'submit',
    'label' => 'Submit',
    'rules' => 'trim|required'
   )
  )
);

Any thoughts on why the validation rule wouldn't run if it wasn't given a value? A big reason I am adding these custom rules is for co-dependent fields.

Thanks again!
- Ian
#4

[eluser]CroNiX[/eluser]
Does it work when they are callbacks instead of extended native rules? I don't have time to test this out, but from the form_validation::_execute() method, it looks like they would.
I actually ran into this a number of years ago and you can check the potential solution in the last post to see if that helps.
http://ellislab.com/forums/viewthread/160059/

If it does, just copy the entire _execute() method from the original library into your MY_Form_validation class to override it, and use
Code:
if ( ! in_array('required', $rules) AND empty($postdata))
as the modified conditional check.

I haven't tested that.




Theme © iAndrew 2016 - Forum software by © MyBB