Welcome Guest, Not a member yet? Register   Sign In
callback from model
#1

[eluser]smith[/eluser]
For those interested in keeping validation inside model. As you all know you can't use callback method from model, or you can but callback function has to be inside controller. I have tried something else, so you can use my method if you want:

make new validation.php that extends CI validation and put it in application/libraries:

MY_Validation.php
Code:
class MY_Validation extends CI_Validation {

    function MY_Validation()
    {
        parent::CI_Validation();
    }
    
    
    function additional_check($array)
    {
        // do something with your data, set error message, return false or true
    $this->set_message('additional_check', 'error');
    return false;
    }
}

in your controller construct load library and forms model:
controller:
Code:
$this->load->library('validation');
$this->load->model('forms');

in your model use callback as you would from controller, but without "callback_" prefix:

model:
Code:
$rules['some_field']   = "required|additional_check";

callback will work without any problem, and you get to keep validation inside model, forms in one model, callbacks in one library. I like it that way, it keeps my controllers pretty clean, so if anyone wants to use this too, be my guest Smile
#2

[eluser]tinawina[/eluser]
Hey this is great! I've been wondering how to clean up my controllers and separate out validation. I'll give your code a whirl. Thanks!
#3

[eluser]tinawina[/eluser]
On second thought...., I am more looking for a way to clean up my validation routines by putting interaction with the dbase in a model. I understand that you have to start and end the callback in the controller that handles validation which is a drag since it has a potential for code replication.

I ended up creating a validation_data model that handles just the database interaction part of callbacks. The validation stuff and the final error message if a callback returns false still reside in my controller. Doesn't reduce my code a ton, but does get closer to MVC.

I guess I don't understand creating a model that doesn't do any interaction with the database? But thanks - you got me at least moving toward truer MVC.
#4

[eluser]smith[/eluser]
what do you mean by interaction with database?
read again, callback is started from model and ended in model, controller gets final data.

in your controller you can call form:
Code:
$this->data['form'] = $this->model_name->form_name();

where form_name is the name of the function inside model. You controller will receive errors, repopulated form or anything you say. all the logic will be inside model.
#5

[eluser]tinawina[/eluser]
Just that where in your code you comment out "do something with the data" -- that's where I mean interaction with the database. I'm trying to follow MVC as much as possible, and so that database interaction should be done in a model. What I ended up doing is just pulling out the query with the database and placing that in the model, and the rest is left to my controller.

validation_data.php Model

Code:
function password_check($table, $password)
{
    $new_password = md5($password);
    $sql = "SELECT " . $table . ".password, " . $table . "_pending.password FROM " . $table . ", " . $table . "_pending WHERE " . $table . ".password = '$new_password' OR " . $table . "_pending.password = '$new_password'";
    $in_use = $this->db->query($sql);
    if ($in_use->num_rows() > 0)
    {
        return false;
    }
    else
        {
        return true;
    }
}

And back at the controller

Code:
function _password_check($table, $password)
{
    $in_use = $this->validation_data->password_check($this->input->post('table'), $this->input->post('password'));
    if ($in_use === false)
    {
        $this->validation->set_message('_password_check', $this->config->item('reg_form_password_check'));
        return false;    
    }
    else
    {
        return true;
    }
}

Unfortunately, you have to do the return false/true routine TWICE but you can't get the validation to work any other way. But at least this moves dbase queries into the model, and leaves the controller to do it's middle man job in the validation process.

Does that make sense?
#6

[eluser]smith[/eluser]
Maybe you didn't understand me. I am still having all dbase function available in the model:
for example, if i want to repopulate the form, i will do this inside model:
Code:
if (!$this->data['vflag'] && $this->data['action']=="edit")
        {
            $sql = "SELECT * FROM some_table where some_id='".$this->data['some_id']."'";
            $query = $this->db->query($sql);
            if ($query->num_rows()>0)
            {
                $row = $query->row();
                $this->validation->some_id      = stripslashes($row->some_id);
                $this->validation->some_field     = stripslashes($row->some_field);
                $this->validation->some_field_2    = stripslashes($row->soem_field_2);
                         }
                   ..............

my example from first post is only howto for situations where you need to do callback from model, during validation. if you do validation inside model then model will not look for your callback function inside itself but he will go to your controller and look for callback function. that way you would have to have all logic inside model and callback functions inside controller. my solution solves that problem by letting you have all callback functions inside a library, and all logic for forms inside a model, so inside controller you will only do:
Code:
$this->data['form'] = $this->model_name->form_name();

i am sorry, this is best that i can explain in english Sad
#7

[eluser]tinawina[/eluser]
No your english is fine! Ok - I'm going to give your approach a try right NOW. Smile Thanks and I'll let you know how it goes.
#8

[eluser]smith[/eluser]
so, your example from above would be:

inside forms model:
Code:
$rules['password']   = "required|check_password"; //callback

inside callback library:
Code:
function check_password($password)
{
    if (password false)
    {
        $this->validation->set_message('check_password', $this->CI->config->item('reg_form_password_check'));
        return false;    
    }
    else
    {
        return true;
    }
}

inside callback library you can see entire $this, except you have to call it like:
Code:
$this->CI->data['something']
or
$this->CI->validation->something
or
$this->CI->input->post('something') ...
#9

[eluser]tinawina[/eluser]
So I have a library, I'll call it Mycallbacks.php, that only includes the callback methods I need, like email_check, password_check, username_check.

Then in my controller I have to make sure to load this library and my model in the constructor.

But what do I have in the actual model? This: $rules['password'] = "required|check_password";

I'm sorry - my brain is not so good.
#10

[eluser]smith[/eluser]
library has to be called MY_Validation.php (watch the case)
inside it you must have:
Code:
class MY_Validation extends CI_Validation {
    function MY_Validation()
    {
        parent::CI_Validation();
    }

... your callback functions here
}

so, this library extend native CI library, and it has access to all variables that native validation has.

in actual model you set validation rules, call views , run validation, populate form (when using edit) etc.

Code:
$rules[’password’] = “required|check_password”;

means that form field named "password" is required and when validation starts function check_password will be called (from MY_Validation.php library).
inside callback function you can check if username/password matches with dbase and return tru/false respectively.

after you finish all job return data to controller, and print it...




Theme © iAndrew 2016 - Forum software by © MyBB