Welcome Guest, Not a member yet? Register   Sign In
Calling a model from another model?
#12

[eluser]Randy Casburn[/eluser]
@mattalexx,
Yes, you are missing something. The documentation is very clear IMHO. If you want to play the Ctrl+F game, please search for this exact phrase:
Quote:Class names must have the first letter capitalized with the rest of the name lowercase.
We are all under pressure to get things done, whether we put ourselves under that pressure, or someone else puts that pressure on us. Sometimes, reading thoroughly will actually save more time than not.

Now, when you have any question about the documentation that you are not satisfied with, I will always encourage you to turn to the code and see what the code does. What I say, or what the documentation says, or what Whozit says is not relavent...what the code does is undeniable. I tried to point this out to you http://ellislab.com/forums/viewreply/417658/

Quote:Class names must have the first letter capitalized with the rest of the name lowercase.

It's that simple.

Best Regards,

Randy
#13

[eluser]mattalexx[/eluser]
Thanks for the good discussion. I see now that there is absolutely no best practice when it comes to underscores; that it's just personal preference. Anyway, back to the original purpose of this post (accessing a model from another model) ...

I'm using the following code and loading the model using this (it seems to work):
Code:
$this->load->model('item_image_model');
print class_exists("Item_image_model")? "loaded" : "not loaded"; // loaded
So I access methods this way:
Code:
$select = Item_image_model::get_select();
Using this syntax isn't mentioned in the docs to the best of my knowledge, so I wanted to run it by you and see if there is a better way to do it.
#14

[eluser]Randy Casburn[/eluser]
@mattalexx -- So when you read this in the docs:
Quote:Once loaded, you will access your model functions using an object with the same name as your class:
$this->load->model('Model_name');

$this->Model_name->function();

What part can't you use in this fashion and what is preventing your from doing it this way?

You can certainly call your methods using "static" calls if you'd like. I don't think the CI folks would recommend that.
#15

[eluser]mattalexx[/eluser]
[quote author="Randy Casburn" date="1214702780"]@mattalexx -- So when you read this in the docs:
Quote:Once loaded, you will access your model functions using an object with the same name as your class:
$this->load->model('Model_name');

$this->Model_name->function();

What part can't you use in this fashion and what is preventing your from doing it this way?

You can certainly call your methods using "static" calls if you'd like. I don't think the CI folks would recommend that.[/quote]

Though this works perfectly in the controller methods, it isn't working from the model files. I get a "Undefined property: Item_model::$item_image_model" error on the second line:
Code:
$this->load->model('item_image_model');
$select = $this->item_image_model->get_select();
The model class is named "Item_image_model" and I'm calling it from within a method of "Item_model".
#16

[eluser]Randy Casburn[/eluser]
Ah, yes... this is a variable scope issue perhaps.

Short answer: You must create an reference to the CI object first.

Reason: The Model object does not have access to the CI object so the "$this" member variable does not refer to the correct object. That's why the static ( Class::Method ) version of the call works and not the object ( Object->Method ) version.
#17

[eluser]mattalexx[/eluser]
So I will have to do something like this (untested code):
Code:
$this->load->model('item_image_model');
$CI =& get_instance();
$select = $CI->item_image_model->get_select();
#18

[eluser]Randy Casburn[/eluser]
yup. It seems, from what we have here, that would be the appropriate way to accomplish what you are trying to do. Wow. What a long way to get here. I took you on a long road. Sorry if that was all my fault.

I can't say I really understand your design though. If every invocation of said method is going to call some method of some other model, this indicates that you have a design problem. This is what was tripping me up.

Can you describe a little more of the use case here so I can understand when/why your model loads a model? I mean under what circumstances?

Just think of me as a thick pile of bricks.
#19

[eluser]mattalexx[/eluser]
By the way, thanks for taking the time to help me out.

This is my design:

I am writing a website for an art gallery. The two objects involved in this are items and item images. The relationship between them is that items have many item images.

In my (possibly skewed) logic, I wrote a method in the item model called get_first_image() that returns that item's main image (the first one that should be shown). You pass it an item_id and you get the item_image_id back.

All database objects involved with the site have a method in their model class called get_select(), which returns an PHP object that will produce an SQL SELECT statement. This statement is prepared and filtered correctly before it is delivered. Here's an example of Item_image_model::get_select():
Code:
class Item_image_model extends Model {

   function Item_image_model() {
      parent::Model();
   }

   function get_select() {

      // Cache object
      static $select;
      if (!is_null($select)) {
         return clone $select;
      }

      // Build base select
      require_once APPPATH."libraries_mine/base/MySQL/SelectQuery.php";
      $select = new SelectQuery("item_images");
      $select->addGroupBys("item_images.id");
      $select->addJoins("

         # Must be connected to items that have more than one quantity and that must be marked shown
         JOIN items
            ON (
               item_images.item_id = items.id
               AND items.show != 0
               AND items.quantity > 0
               )
              
         # Those items must be connected to valid categories
         JOIN categories_items
            ON items.id = categories_items.item_id
         JOIN categories
            ON (
               categories_items.category_id = categories.id
               AND categories.in_nav != 0
               )
              
         # Those items must also be connected to an artist
         JOIN artists
            ON items.artist_id = artists.id
         ");
      $select->addOrderBys("
         item_images.sequence ASC,
         item_images.id ASC
         ");

      // Return
      return clone $select;
   }
  
   // ...

}
Within the aforementioned method Item_model:get_first_image(), I need to retrieve a select object that represents item images, so I am doing this:
Code:
class Item_model extends Model {

   function Item_model() {
      parent::Model();
   }

   function get_first_image($items_id) {
      
      // Retrieve data from session cache
      $items_first_images = $this->session->userdata('items_first_images');
      
      // If not in session cache, add it
      if (!isset($items_first_images[$items_id])) {

         // Get a SelectQuery object for item_image
         $this->load->model('item_image_model');
         $select = Item_image_model::get_select();
        
         // Filter by item
         $select->addWheres("
            item_images.item_id = ".$items_id."
            ");
        
         // Only need the item_image_id
         $select->setFields("
            item_images.id
            ");
        
         // Query the database
         $q = $select->Query();
        
         // Write into cache
         $items_first_images[$items_id] = $q->fetchValue("id");
         $this->session->set_userdata('items_first_images', $items_first_images);
      }
      
      // Return item_image_id
      return $items_first_images[$items_id];
   }
  
   // ...

}
Please let me know whether you need more information to accurately judge whether my MVC practices are off.

And again, thanks for your help.
#20

[eluser]Randy Casburn[/eluser]
Quote:...judge whether my MVC practices are off.

Well, this being a religion and all ;-), I'll pass on making judgment. I'll tell you that the split between the roles of the Model and Controller has been cloudy forever. I'll also tell you that I see nothing really _wrong_ with what you've done. There are thirty different ways to peel a grape kind of thing...right?

It appears from looking at the CI internals that CI was designed with the idea that your Model functionality would be consolidated _functionally_ within a single file. That doesn't mean that you cannot use multiple Model files. Some times one might call multiple model files from the Controller and consolidate the data in the Controller prior to sending it to the View for example. But now I'll get flamed for breaking MVC because of the cloudy delineation between Model and Controller (academically). Either way, it seems CI prefers you to consolidate the data gathering routines into a single file. Then CI expects you to call that single Model to gather your data so you can deliver that data to your View.

That means all the dependency you've created here (and segregated into separate files) is expected to be in a single file from CI's perspective.

So here is the question. Do you ever use these classes or the functionality found in them independently of one another? Are they 'generally' used together and rarely used separately. If this is the case, then you've substantiated the CI design principles. Right? You should probably combine the functionality into a single class and be done with the problems this is causing you. Then consider this in future designs.

If they are always used independently, then consider that in future designs too. Knowing that you'll have to take special care to make the CI object available inside you're additional class structures.

We all do it both ways depending on the nature of what we are doing. I will tell you, though, given what I know, and nothing more, of this situation, I would consolidate this Model into a single class unless it is completely unwieldy. I would also consider the Outer Joins as a separate specialized DB class of sorts. But that's because I tend to consolidate my queries as much as I can.

Hope this is helpful.

Randy




Theme © iAndrew 2016 - Forum software by © MyBB