CodeIgniter Forums
Using models within models - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Archived Discussions (https://forum.codeigniter.com/forumdisplay.php?fid=20)
+--- Forum: Archived Development & Programming (https://forum.codeigniter.com/forumdisplay.php?fid=23)
+--- Thread: Using models within models (/showthread.php?tid=9933)



Using models within models - El Forum - 07-13-2008

[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!


Using models within models - El Forum - 07-14-2008

[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


Using models within models - El Forum - 07-14-2008

[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.


Using models within models - El Forum - 07-14-2008

[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();

   }
}



Using models within models - El Forum - 07-14-2008

[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.


Using models within models - El Forum - 07-14-2008

[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


Using models within models - El Forum - 07-14-2008

[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


Using models within models - El Forum - 07-14-2008

[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...


Using models within models - El Forum - 07-14-2008

[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.


Using models within models - El Forum - 07-14-2008

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