As a mostly self-taught programmer I'm late to the game when it comes to design patterns and such. I'm writing a labor management webapp using CodeIgniter.
I did a bit of MVC ASP.NET/C# and Java at school, and the convention was that your model mainly consisted of classes that represented actual objects, but also abstracted all the database connection and such...which is pretty standard MVC stuff from what I've gathered.
I imagine I'm right in saying that CI abstracts the database connection completely out of sight (unless you go looking), which is par for the course, and the models you can create can abstract the 'generic' CRUD methods a bit more to create some methods that are more useful for the specific model.
The thing I have a problem with, because it's different to what I'm used to with MVC, is that whenever you say...return a row from a database, the convention is to just put it in an associative array or standard object with the properties representing the data from the row.
In ASP you'd have actual classes that you could construct to store this information. For example you'd have a House
class and the data would be stored as properties (e.g. bedrooms
, bathrooms
, address
) and the methods would represent useful things you could do with the data (e.g. printInfo()
may print("$address has $bedrooms bedrooms and $bathrooms bathrooms!')
).
I'm getting the impression — just from code I've seen around the Internet — that this isn't the standard way of doing things. Are you supposed to just use arrays or generic objects, and say...do $this->house_model->print_info($houseobject)
instead of $houseobject->print_info();
?
Thanks.
Despite its claims to the contrary, Codeigniter does not use MVC at all (In fact, very few web frameworks do!) it actually uses a PAC (Presentation-abstraction-control) architecture. Essentially, in PAC the presentation layer is fed data by a presenter (which CodeIgniter calls a controller) and in MVC the View gets its own data from the model. The confusion exists because of this mislabeling of MVC.
As such, CodeIgniter (and most of the other popular web frameworks) don't encourage a proper model but just use very rudimentary data access its place. This causes a large set of problems because of "fat controllers". None of the code which relates to the domain becomes reusable.
Further reading:
This is a widespread point of confusion in the PHP Community (The MVC vs. PAC article identifies the problem as stemming from the PHP community. that was written in 2006 and nothing has changed, if anything it's got worse because there are more frameworks and tutorials teaching an erroneous definition of MVC.) and why people looking at "MVC" PHP code who have come from a background outside web development understandably become confused. Most "MVC" implementations in PHP are not MVC. You are correct in thinking models should be properly structured, it's CodeIgniter that's wrong to label itself as MVC.
CodeIgniter is very flexible when it comes to following the MVC pattern and it's really up to you how much you want to enforce it. Most of the CodeIgniter code you will find online is exactly like you describe, the Models are just a collection of methods really, and don't strive to strictly represent an object.
You can, however, code that way too if you so like within CI (and this is something I often do). It makes the code much more maintainable and readable, and just seems better all around.
PS - If you're just getting into MVC in PHP, you might want to look around a little. Frameworks like CodeIgniter and CakePHP are (somewhat) of a previous generation. CI was initially written for PHP4 where OOP support was kinda spotty in PHP. A fork of CI, called Fuel, was specifically created to address this issue (though I believe at some point, they just decided they would be better served by rewriting it from scratch). CI does have the advantage of having a lot of documentation and help online since it is more widely used than Fuel.
controller
// get the houses result from the model
// return it as an object
if( ! $houses = $this->house_model->findHouses($search) )
{ // if no results - call a no results view
$this->load->view( 'no_results', $data );
}
else
{
// pass the houses object to data so it automatically goes to view
data['houses'] = $houses ;
// Call your view
$this->load->view( 'house_results', $data );
}
view
// we already know we have at least one house,
// thats what the controller is for, so we dont need to do an isset() etc for $houses
foreach $houses as $house :
echo 'This fine house at ' . $house->address . 'has '. $house->bedrooms . ' bedrooms and ' $house->bathrooms . ' bathrooms' ;
endforeach ;
obviously there are different ways to create that final sentence in the view, but the idea is that by the time we get to the view - its as simple as possible.
so for complex queries like Show me all the houses next to the good schools, with 2 bedrooms and room for my pet Ocelot.
Thats what happens in the model. all of the messy conditions and business rules. views should be specific - if you dont have results - then just show a no results view. Versus -- doing a results check in the view, and then changing the display based on no results. the more specific you make the view, the easier it will be to build out, and it will encourage you to make the choices in the controller and model.