Welcome Guest, Not a member yet? Register   Sign In
Using models within models
#1

[eluser]vendiddy[/eluser]
Is it possible to load a model within a model? The following code (which is a method from a model) does not work. When I call $this->user_model, it is not defined. However, if I put 'user_model' and 'task_model' in the $autoload['model'] array then I can access the models without a problem. Am I doing something wrong?

Code:
function create_new()
    {
        
        //Make sure user is logged in
        $this->load->model('user_model');
        $user_id = $this->user_model->get_logged_in_user_id();
        if ($user_id === FALSE) {
            //User is not logged in
            return FALSE;
        }
        
        $this->load->model('task_model');
        $task = $this->task_model->create_new();
        $data = array(
            'title' => 'Title',
            'description' => 'A description.',
            'task_id' => $task->id,
            'creator' => $user_id,
        );
        $this->db->insert('projects', $data);
        $id = $this->db->insert_id();
        
        return $this->_get_project($id);    
    }

Thanks!
#2

[eluser]MaDe[/eluser]
That's some kind of scope issue for $this. Try using this one:

Code:
function create_new()
{
        $CI =& get_instance();
        //Make sure user is logged in
        $CI->load->model('user_model');
...
}

Regards,
Marc
#3

[eluser]Colin Williams[/eluser]
In my eye, what you're doing should happen in the Controller. The model should only have to deal with saving and retrieving data, not user access checks. The Controller is the "traffic cop" of an MVC application.

This also holds true with your task model. Consider this controller method.

Code:
function create()
{
        //Make sure user is logged in
        $this->load->model('user_model');
        $user_id = $this->user_model->get_logged_in_user_id();
        if ($user_id !== FALSE) {
            $this->load->model('task_model');
            $task = $this->task_model->create_new();
            $this->other_model->create_new($task, $user_id);
        }

        // [...]
}

And then your Model:

Code:
function create_new($task, $user_id)
    {
        $data = array(
            'title' => 'Title',
            'description' => 'A description.',
            'task_id' => $task->id,
            'creator' => $user_id,
        );
        $this->db->insert('projects', $data);
        $id = $this->db->insert_id();
        
        return $this->_get_project($id);    
    }

You see how we shift the business logic into the Controller. Just a suggestion.
#4

[eluser]gon[/eluser]
I agree with Colin Williams.

But it's true that sometimes you need to access some model from another one.
MaDe's suggestion works, but if you need to access other models from more that one method, you could get the reference to CI instance at the constructor.

Code:
class Examplemodel extends Model {
  
   var $CI;

   function Examplemodel() {
      parent::Model();
      $this->CI =& get_instance();
   }

   function methodexample() {
       $info_from_another_model = $this->CI->another_model->get_info();

   }
}
#5

[eluser]Colin Williams[/eluser]
Quote:But it’s true that sometimes you need to access some model from another one.

Really? I disagree that it is needed, but I do see that it could potentially abstract some of the process if a particular model method always depends on data from a secondary source. At some point, I would merge models like this, even if they managed two or more different sources (tables):

Code:
class Project_model extends Model {

function save_project(){}

function save_task(){}

function get_project(){}

function get_task(){}

}

It comes down to personal preference I guess.
#6

[eluser]MaDe[/eluser]
[quote author="Colin Williams" date="1216047571"]It comes down to personal preference I guess.[/quote]
I think so, too. Sometimes you need to call one or two functions from another model, because sometimes model interact Wink So the "get_instance" thing works good, if you don't need it often. If you need it too often, you should think over your models, I agree.

Regards,
MaDe
#7

[eluser]vendiddy[/eluser]
Thanks for the helpful answers everyone!

I will follow Colin's suggestion to move the user access checks into my controllers. However I do feel that models sometimes need to call other models. In my situation, when a project is created, a related task also needs to be created. Shouldn't every object only have a single responsibility? Then again, I guess it "comes down to personal preference." Smile
#8

[eluser]Colin Williams[/eluser]
Quote:In my situation, when a project is created, a related task also needs to be created.

I think you could get by with a Project Model that creates projects and tasks. Either this or create some sort of events/hook system.

Quote:Shouldn’t every object only have a single responsibility?

Do objects in the real world only ever have a single responsibility? Ha! I wish...
#9

[eluser]vendiddy[/eluser]
I guess I meant as narrow of a responsibility as possible.

The events/hook system idea sounds interesting. I ran into this library called khevent (http://ellislab.com/forums/viewthread/69753/) and will try messing around with it.
#10

[eluser]wiredesignz[/eluser]
You can also extend Tasks_model from Projects_model and use Projects::method() as needed.




Theme © iAndrew 2016 - Forum software by © MyBB