• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
At what point do you seperate things into different models?

#1
Let's say you have a model called "Range"

A Range model might consist of a name, a description, and an image.

Then let's say you have a model called "Product".  You could have several Products to a Range.  A Product model would consist of a size, a colour and a price.

OK, so the above is fine.  However, I find that in places I am doing MySQL joins on the Product and Range tables.  For example, I might want to display a table of all Ranges along with their associated size, colour and price values from the Product table.  This really starts to blur the lines between the separate models.  Which model should be responsible for generating such information, the Range or the Product?

It's got me thinking, should Range and Product all be part of the same model?  The problem with that approach is that you might have a "Customer" and an "Order" model to represent customers and purchases.  Customers are related to Orders, and Orders are related to Products, and Products are related to Ranges.  At some point there are going to be requirements to join some or all of this information together in different controllers and views. You could therefore end up with one giant model which encompasses everything, which would not be good either.

Thoughts?
Reply

#2
(06-20-2016, 04:45 AM)CINewb Wrote: Thoughts?

It might sound weird, but lately we've been using two different model types, one for your typical model that handles user input validation and DB actions, and a "listing" model type that only gets minimal required information from DB to just fill in HTML tables.

Controller for ranges would look something like this
PHP Code:
$range $this->range->get($range_id);
$products $this->product_listing->where('range'$range->id())
 
   ->limit($per_page)
 
   ->get(); 

And order page controller could look like this
PHP Code:
$order $this->order->get($order_id);
$customer $this->customer->get($order->customer_id);
$products $this->order->getProducts(); 

Order model
PHP Code:
...
public function 
getProducts()
{
 
  $this->load->model('product_listing');
 
  
   
// get product IDs for this order from DB and assign it to "$product_ids" array)
 
  $q $this->db ....

 
  return $this->product_listing->where('id'$product_ids)
 
     ->get();
}
... 

I found joining everything does not work very well, it's usually quicker to get all related IDs then link everything together in PHP side, lets say if you want products over multiple orders, it seems better solution to figure out what individual products you need, then do "WHERE IN" with unique child IDs than trying to join everything together, specially when you have 4-5 tables or more (there's a story behind that conclusion, involves my first day at my current position 4 years ago and someone's legacy code  Tongue ).
Reply

#3
If you find that you need things in different models then create a MY_Model and extend all of your models from the
MY_Model
What did you Try? What did you Get? What did you Expect?

Joined CodeIgniter Community 2009.  ( Skype: insitfx )
Reply

#4
This is a good question but it is caused by the idea that a model should relate to a single table in the database. I have never found this practical or to be possible in any real sense exactly because of joins, except in the most simple of applications.

I recently changed to using models as far more complex entities, with thin controllers. So the controller would call a Product_display_model say and give it the range it wants. The Product_display_model would get the range, all related products, and return the data for the page. A Product_management_model would be used for adding and updating products etc. A Basket_model would be responsible for the shopping cart, an Order_model for dealing with orders etc. All of these would interact with the product table, range tables, order tables etc.

For more complex patterns I would use libraries too, but for a shop it can be managed well with just models.

The design of the different models' areas of responsibility is quite critical here. Sometimes it is easy to divide them up as in this case, but if you get it wrong, revisiting it and reworking it can be a real pain, and often a complete rewrite.

Now my controllers are very thin. They just do the 'who is this, are they allowed, what are they asking for, what views do I need' and then output the page.

Best wishes,

Paul
Reply

#5
(standard disclaimer that some people will not agree) For complex operations models can call other models. You can have a Categorypage model call a Products model and return the relevant info to the controller for say the product names and price range for a category page. Versus a Productpage model that calls the Products model to get product details, variations available for sale, all pricing, etc. Versus the Cart model that calls the Products model to confirm the price for a specific product, and the product is still in stock. If your app does start to have a lot of models I highly recommend using folders. So the more general models are on top, and they call the more specialized models which are in clearly labeled folders.

While I'm rambling - when you are naming your models - consider how its going to read when you are calling them in your controller. Also for a long time i was naming models Product_model, Cart_model, etc. Then I saw a tutorial where they abbreviated it to Product_m, and I thought that was very clever and used that for a while. Finally I realized it was completely unnecessary. You can simply name your models Cart, Productpage, etc. It saves typing time and is easier to read.
Reply

#6
Is is ok for a model to call another model? I never do that, but thinking about what you said, I can see where that makes a lot of sense. I always imagine the process as a pure controller calls models to get data, or libraries, or helpers, makes decisions about output and then selects views to display the right resulting page.

This might be one of those things where it is opinion based. Perhaps a poll might be needed to see what people think.

As for naming, I much prefer the convention of _model. For example:
PHP Code:
$this->cart->get_basket_items() 
In this example, is 'cart' a method in the current controller, or is it a library, or is it a model, or a helper?

I prefer the convention of this:
PHP Code:
$this->cart_model->get_basket_items() 
No question about this. It is a model. Personally this is one thing I would have no objection if CI actually enforced.

Also helps to prevent naming issues like
PHP Code:
$this->cart->check_basket_items()
$this->cart_model->get_basket_items()
$this->cart_helper->delete_basket_items()
$this->cart_library->save_basket() 

However I have never agreed that good code is necessarily clever or short, I want it to be clear, logical and DRY. Personally have no interest in typing less, I just want to know what every line is actually doing, preferably without comments. But coding would be a lot less creative if there was only one way of doing things.

Paul.
Reply

#7
Website I'm working on today has 132 tables in the database, and 56 models. The models are organized to deal with certain tasks/actions where similar data is returned, inserted, deleted, updated. I'd suggest just doing what you need to do to keep things clear, maintainable, and clean. Do what feels natural to you, especially if you are the one that might come back in 3 or 4 years and need to make some changes.
Reply

#8
Wow, that is a huge number of tables. My biggest site has about 20. What on earth do they need so many tables for?
Reply

#9
We tend to think of models as an object, not necessarily a single table (although some are), more the actions that can be applied to an object. We have one "listing" model that pulls static lists for everything in our app and a model for each object.

Ex:

- a model named "role" that has insert, update, delete, get methods
- a model named "user" that has the same methods, as well as a get_roles method

The "get_roles" method joins from user to role to pull a list of roles for a given user id. Since the data it returns is specific to a user it's in the user model and called using $this->user->get_roles( $user_id ).
Reply

#10
PaulD Wrote:Wow, that is a huge number of tables. My biggest site has about 20. What on earth do they need so many tables for?

We have 139 tables and 37 models in our app. The number tends to balloon after a few years of adding new features to the same project.
Reply


Digg   Delicious   Reddit   Facebook   Twitter   StumbleUpon  


  Theme © 2014 iAndrew  
Powered By MyBB, © 2002-2021 MyBB Group.