1

Hi I hope you can help me with this. I have seen many of the same questions on this issue and none of them works for me.

I am using Codeigniter 2.2.2 and trying to create form validation in model so it can be accessible by multiple controllers. The form validation was not able to return correctly on custom callbacks declared in the model.

// in Model
function validateErrors() {
   $rules = array(
      array('field'=>'username', 'label'=>'User', 'rules'=>'trim|required|callback_userPrefix'),
      array('field'=>'password', 'label'=>'Password', 'rules'=>'trim|required|callback_passwordNotEmpty'),
   );

   $this->load->library('form_validation');
   $this->form_validation->set_rules($rules);
   if ($this->form_validation->run() == FALSE) {
      $errors = array();
      foreach ($rules as $r)
          $errors[$r['field']] = $this->form_validation->error($r['field']);
      return $errors;
   }
   return false;
}

public function userPrefix() {
   $find = 'user_';
   if (strpos($this->input->post('username'), $find) != 0) {
      $this->form_validation->set_message('userPrefix', 'Username not allowed.');
      return false;
   }
   return true;
}

public function passwordNotEmpty() {
   // not the actual callback just an example
   if (empty($this->input->post('password'))) {
      $this->form_validation->set_message('passwordNotEmpty', 'Password cannot be blank.');
      return false;
   }
   return true;
}

so it can be accessed in Controller like:

// in Controller
if ($this->input->post()) {
   $this->load->model('ModelName','model1', true);
   $validation_errors = $this->model1->validateErrors();
   if ($validation_errors === false) {
      // continue saving record
   } else {
      print_r($validation_errors); exit;
   }
}

I wanted to create form validation every user login. But since multiple controllers make use of the same validation, I declared the validation and their custom callbacks in the model to minimize coding length in controllers (hopefully minimize).

Also, this answer says you can do the form validation in the model (also showing callbacks declared in model supposedly work). I tried that but wouldn't work for me.

Can anyone help me in this? Thank you very much!

4
  • 2
    Maybe this is a reason to upgrade to Codeigniter 3? There are huge advantages with upgrading and there are not that many breaking changes. Then you could use callable in your models like: codeigniter.com/user_guide/libraries/… Commented Jun 22, 2016 at 3:07
  • @cartalot does that mean it cannot be done? I cannot upgrade to v3 because I can only access certain modules on my current company's system Commented Jun 22, 2016 at 3:24
  • share your html with us, then it will be easier to figure out what's going on. Commented Jun 22, 2016 at 4:26
  • 1
    are you using HMVC in yout CI? (i mean, modular CI)? if so, you have to trick a bit the Form_validation Class.... Commented Jun 22, 2016 at 10:20

3 Answers 3

2

Call the extra methods separately like:

// in Model
function validateErrors() {
   $rules = array(
      array('field'=>'username', 'label'=>'User', 'rules'=>'trim|required'),
      array('field'=>'password', 'label'=>'Password', 'rules'=>'trim|required'),
   );

   $this->load->library('form_validation');
   $this->form_validation->set_rules($rules);

   if ($this->form_validation->run() == FALSE) {

        // something something 
   }
   // 
   elseif( $this->userPrefix() == false)
   {
      // something 
   } 
   elseif( $this->passwordNotEmpty() == false)
   {
      // something 
   } 
   else{ return true;  } 

}

Callbacks are very nice if you have an array of data - like if you were validating a group of user names where the field is username[]. But I've just gone through some questions about what callbacks can and cannot do and I think the above code is actually clearer. Also fyi - $this->input->post('fieldname') - is always available in your model. In other words its not dependent on being part of codeigniter form validation.

Sign up to request clarification or add additional context in comments.

Comments

1

I have done a workaround, thanks to @cartalot and @marcoFSN's suggestions. I did have to modify the Form_validation class (thanks @marcoFSN) and I really can't call custom callbacks declared in the model via set_rules method, so I had to call each custom callbacks separately (thanks @cartalot).

Here is my code:

// in Model
function validationErrors() {
   $rules = array(
      array('field'=>'username', 'label'=>'User', 'rules'=>'trim|required'),
      array('field'=>'password', 'label'=>'Password', 'rules'=>'trim|required'),
   );
   $this->load->library('form_validation');
   $this->form_validation->set_rules($rules);

   $errors = array();
   if ($this->form_validation->run() == FALSE)
      foreach ($rules as $r)
         $errors[$r['field']] = $this->form_validation->error($r['field']);
   if (!$errors['username'])
      if ($this->userPrefix( $this->input->post('username'), 'username'))
         $errors['username'] = $this->form_validation->error('username');
   if (!$errors['password'])
      if ($this->passwordNotEmpty( $this->input->post('password'), 'password'))
         $errors['password'] = $this->form_validation->error('password');

   if (!empty($errors)) return $errors;
   else return false;
}

function userPrefix($value, $field) {
   $find = 'user_';
   if (strpos($value, $find) != 0) {
      $this->form_validation->set_field_error($field, sprintf('Username not allowed.'));
   }
   return (strpos($value, $find) != 0);
}

function passwordNotEmpty($value, $field) {
   if (empty($value)) {
      $this->form_validation->set_field_error($field, sprintf('Password cannot be blank.'));
   }
   return (empty($value));
}

I also added the function set_field_error to the Form_validation class to be able to set custom error messages :

public function set_field_error($field, $value)
{
    if (isset($this->_field_data[$field]))
        $this->_field_data[$field]['error'] = $value;
    return;
}

With this, I can now use the model function validationErrors in the controller like:

if ($this->input->post()) {
    $this->load->model('ModelName', 'model1', true);
    $validation_errors = $this->model1->validationErrors();
    if ($validation_errors === false) {
        // continue saving data
    } else {
        print_r($validation_errors);
        exit;
    }
}

Thanks again to the people who helped me come up with this workaround. I hope this may help others having the same problem as I did.

1 Comment

Glad you got through this. Definitely encourage your company to upgrade to version 3 - its relatively easy to do and besides the additional security - its much faster performance.
0

This is based on @cartalot's idea, it would be better to do this, because this will check all custom validation methods when validation fails:

if ($this->form_validation->run() == FALSE) {
        $standard_error = form_error($field)
        if($model_object->model_method($post_value['some]) == FALSE) 
        {
            //here manually fill error for display on form
        }
        if($model_object->model_method2($post_value['some2]) == FALSE) 
        {
            //here manually fill error for display on form
        }
   }

EDIT (for CI3): Even better, you could define model method that only returns rule array, and then before validation->run() setup this rule(s) from your $model_object->method_that_returns_rule_array(). That rule(s) can contain callable anonymous function - more info here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.