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:
MVC vs. PAC
The M in MVC: Why Models are Misunderstood and Unappreciated
Model-View-Confusion part 1: The View gets its own data from the Model
The Fat Controller
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.
Related
Newbie question about MVC structures here. So in an MVC, I currently have a page in my Views to display a list of results from a database query, in this bit of code I instantiate a class, run a method for sql query, and at last there's a for each loop and then displaying it with divs.
So my question is, if this bit of code is considered business logic and should be in a method in the Model, or is it part of the Views?
I hope you understand what I mean =) Thanks!
$listholder = new Categories_Model();
$data = $listholder->getCategories();
$i = 1;
foreach ($data as $row) {
if ($i & 1) {
echo '<div id="horizontalContainer" style="float: none; height: 50px";>';
echo '<div id="listoverview1">'.$row['catname'].'';
echo '</div>';
} else {
echo '<div id="listoverview1">'.$row['catname'].'';
echo '</div></div>';
}
$i++;
}
No, that code is mainly view code. It only purpose is to allow an external process (a human) to see data in a form it likes. Assuming that the check for the first row is only important to the external process, not to your business logic
Model code shapes, gets, and sets data, some of which is persisted (database etc.) and some of which is calculated on demand
Some generalised, and simplified examples on things a model or view should do:
Model calculates the total of some financial figures
View flags each even numbered row so it can be rendered with a shaded background in the view
Also, in a classical MVC system, your first two lines of code would be in the controller, which would organise the dataset by using models and model methods to get data. The MVC system would then pass that data to the selected view to render
There are plenty of PHP based MVC frameworks like CAKE, KISS etc (not all are very good!). If you have a few dollars in your pocket, save yourself some time and stress, and load up Microsoft MVC
From your question you might have some understanding of MVC that has nothing to do with what other developer think what MVC is. That can happen, especially nowadays as some frameworks have used these three letters as a catchphrase without providing it actually.
From the code you outline in your question I'd say it is a typical Transaction Script and there is no specific kind of model nor view layer involved.
The transaction script transports business logic and you do not need to speculate a lot about view or models, just keep everything inside the transaction script.
Your transaction scripts will tend to become spaghetti code, however, with some little refactorings here and there over time you should be able to reduce duplicate code and I do not think your application will grow that large that it is actually not feasible any longer keep it maintained in transaction scripts.
So why being concerned about MVC if everything is in order with some other, well proven pattern?
Taking as an example Rails or CakePHP, your code doesn't follow the mvc pattern.
Model should only contain business logic (query/do something with fields of an object)
Controller should work "only" with receiving requests of webpage with params and send back the correct page
View Is basically an html page only
Obviusly this is a very short briefing of what html is.
In your case, the idea would be:
$listholder = new Categories_Model();
$data = $listholder->getCategories();
Which is a controller code (usually), getCategories is a Model method (ok as is).
Then the controller will send some parameters to view which will know how to display those to the user, in this case your $data variable.
Imagine something like printMyView($view_file_path, $data)
The view will be something like this:
categories/show/">';
categories/show/">';
See http://php.net/manual/en/control-structures.alternative-syntax.php for alternative control structure syntax (quite nice). Maybe URLS are written better with sprintf or things like that (not how I did).
Basically you need 3 files (to split things logically), and the law is quite easy: don't write ever html in Controller, nor in Model.
The goal of MVC design pattern is to separate the presentation from the domain business logic. For that reason the business logic stays exclusively in model layer (model is a layer not any single class, if you have a class named Model, you are doing it wrong), whole the presentation layer contains views an controllers.
Controller instances are one that deal with user's requests, and change the state of model an view instances.
The view instances are the ones, that contain the presentation logic (just like domain objects contain the business logic in model layer). Views acquire information from model layer and decide, which templates will be used, or even whether template is even necessary. Views generate the response in your web site, and sending of redirect header is form of response too, which does not require any templates at all.
Also, you have to understand, that it is impossible to use classical MVC pattern with PHP (and highly complicated and impractical in the few web development, that would provide such option). Instead you would be using one of the MVC-inspired patterns.
These patterns are mostly distinguishable by how* view acquires information from model layer. The main options are: Model2 MVC, MVP, MVVM and HMVC.
In your case, the view should acquire the set of categories from model layer and then, if list is not empty and no exceptions were thrown, select a template which generates an unsorted HTML list.
The business logic would stay in the the model layer (in the domain object, which deals with categories), the presentation logic in the view and the process of turning it all in HTML - in the template, which view picked.
Shouldn't models just describe data that will be passed from a controller to a view? Doesn't that make models unnecessary in weakly typed languages? In PHP, they are doing DB work in models, but isn't that wrong? As I see it, models are just unnecessary in weakly typed languages...
There are some misconceptions about the term model. Microsoft's MVC3 framework has the concept of a view-model, which is simply the data you use to render your views. This isn't however what the M stands for exactly in MVC. The model includes your business entities. We have thin controllers and fat models, but very thin view models. Our controllers make calls to services that perform business logic, and the controllers never do this logic themselves. We then translate our business entities (our data models) and convert them into a lightweight view model, which can be used for rendering a view.
So to answer your question
Shouldn't model just describe data that will be passed from controller to view?
Then perhaps what you are really asking is aren't view-models unnecessary? I'm not sure why you think this. View model + view makes the result. In PHP it can be helpful to define a class with easily accessible properties on it. This is just sensible for clarifying your expectations and prevents you from calling methods with hideously long sets or arguments. In JavaScript there is no need to define a view model as such, you just push the properties onto a new object and pass it along with your view to your view rendering logic. This is more a reflection of the OO pattern these languages use and not the fact that they are weakly typed.
If you are asking if model is unnecessary, then you have missed the purpose of the MVC architecture. A big part of MVC is that you separate your concerns. Why apply any architecture to your code? I am sure you can find a better explanation of the motivation behind MVC than I can give you.
A model is a useful conceptual tool, even if it's not strictly necessary in PHP to separate it from the DB code e.g. you can have a data object associated with each table that encapsulates some business logic, or define a set of business entities that aggregate the data across tables into domain-specific objects that the controllers can then use, or just have one monster DB object that has all the access functions and returns the entities. This has definite advantages over having DB code directly in use by the controllers:
If you are defining complex data structures that run across DB tables, you don't want to do that in controller code due to the risk of duplication - far better to have a single definition that enforces consistency across the system. Although this can introduce dependencies, having one function/object that defines that data makes it easy to find out where the data is used so you can fix things.
Third party maintenance is far easier if there's one place to go to where all the data structure definitions are found.
It makes unit testing easier if you can swap out the whole model or parts of it and replace it with mock object(s) that will provide test data
It makes controllers lighter and therefore more readable and maintainable
So you could argue that it's not necessary, but it helps a lot.
I've always seen models as a tool to provide data. That means that your controller doesn't ever have to worry about the data source, and if you want to switch from using a database to XML files then you only have to swap out your model.
So long as you have some data provider abstraction. Some Models will do low level validation (tightly coupled to the storage engine - null checks etc) but the controller "should" do all of the business logic/validation.
I personally have a thin struct like class that is mapped to each table (all implementing IDataStruct). This struct, or a collection thereof, is the only thing that moves between the DomainObject and the DataProvider. I can then enforce via my interface what datastruct I should be receiving. This is not a silver bullet but I have found it to work well (Makes things like caching and unit testing quite easy)
I hope this hasn't confused the issue.
Now that I have read an awfull lot of posts, articles, questions and answers on OOP, MVC and design patterns, I still have questions on what is the best way to build what i want to build.
My little framework is build in an MVC fashion. It uses smarty as the viewer and I have a class set up as the controller that is called from the url.
Now where I think I get lost is in the model part. I might be mixing models and classes/objects to much (or to little).
Anyway an example. When the aim is to get a list of users that reside in my database:
the application is called by e.g. "users/list" The controller then runs the function list, that opens an instance of a class "user" and requests that class to retrieve a list from the table. once returned to the controller, the controller pushes it to the viewer by assigning the result set (an array) to the template and setting the template.
The user would then click on a line in the table that would tell the controler to start "user/edit" for example - which would in return create a form and fill that with the user data for me to edit.
so far so good.
right now i have all of that combined in one user class - so that class would have a function create, getMeAListOfUsers, update etc and properties like hairType and noseSize.
But proper oop design would want me to seperate "user" (with properties like, login name, big nose, curly hair) from "getme a list of users" what would feel more like a "user manager class".
If I would implement a user manager class, how should that look like then? should it be an object (can't really compare it to a real world thing) or should it be an class with just public functions so that it more or less looks like a set of functions.
Should it return an array of found records (like: array([0]=>array("firstname"=>"dirk", "lastname"=>"diggler")) or should it return an array of objects.
All of that is still a bit confusing to me, and I wonder if anyone can give me a little insight on how to do approach this the best way.
The level of abstraction you need for your processing and data (Business Logic) depends on your needs. For example for an application with Transaction Scripts (which probably is the case with your design), the class you describe that fetches and updates the data from the database sounds valid to me.
You can generalize things a bit more by using a Table Data Gateway, Row Data Gateway or Active Record even.
If you get the feeling that you then duplicate a lot of code in your transaction scripts, you might want to create your own Domain Model with a Data Mapper. However, I would not just blindly do this from the beginning because this needs much more code to get started. Also it's not wise to write a Data Mapper on your own but to use an existing component for that. Doctrine is such a component in PHP.
Another existing ORM (Object Relational Mapper) component is Propel which provides Active Records.
If you're just looking for a quick way to query your database, you might find NotORM inspiring.
You can find the Patterns listed in italics in
http://martinfowler.com/eaaCatalog/index.html
which lists all patterns in the book Patterns of Enterprise Application Architecture.
I'm not an expert at this but have recently done pretty much exactly the same thing. The way I set it up is that I have one class for several rows (Users) and one class for one row (User). The "several rows class" is basically just a collection of (static) functions and they are used to retrieve row(s) from a table, like so:
$fiveLatestUsers = Users::getByDate(5);
And that returns an array of User objects. Each User object then has methods for retrieving the fields in the table (like $user->getUsername() or $user->getEmail() etc). I used to just return an associative array but then you run into occasions where you want to modify the data before it is returned and that's where having a class with methods for each field makes a lot of sense.
Edit: The User object also have methods for updating and deleting the current row;
$user->setUsername('Gandalf');
$user->save();
$user->delete();
Another alternative to Doctrine and Propel is PHP Activerecords.
Doctrine and Propel are really mighty beasts. If you are doing a smaller project, I think you are better off with something lighter.
Also, when talking about third-party solutions there are a lot of MVC frameworks for PHP like: Kohana, Codeigniter, CakePHP, Zend (of course)...
All of them have their own ORM implementations, usually lighter alternatives.
For Kohana framework there is also Auto modeler which is supposedly very lightweight.
Personally I'm using Doctrine, but its a huge project. If I was doing something smaller I'd sooner go with a lighter alternative.
I'm learning the Zend Framework and it uses a MVC model.
I still have not got my head around what MVC Model, View, Controller is.
What are the three different areas for and what would the program flow look like?
M - Models - are often the biggest source of confusion. These are the parts of your application that do all the 'heavy lifting' - they handle database access, perform the complex application-specific logic and are responsible for most of what your application 'does'. Unlike Views and Controllers, the Zend Framework doesn't have a base class for Models - this is because there's no real consistency in what they do. Some frameworks (like Ruby on Rails) try to present some sort of database-wrapper as a base for Model, but there are many cases (3rd party feed/API, static files, non-persistent calculations, concepts that span multiple tables...) for which this is, at best, a misleading practice. The Model is the part of the application where you're still forced to program and the framework can't really save you from it.
V - Views - are the simplest components here. They should be simple PHP/HTML templates. They're given view objects, arrays, strings, etc. which they then put into a page. There shouldn't be much (if any) complex logic here - loop over these, display this (if defined), zebra stripe this table and whatnot. There's some magic happening with View Helpers (such as the helper that magically renders a Zend_Form), but that's not essential to understanding the overall system.
C - Controllers - In the broadest sense, the controller is responsible for taking user requests, sending them off to Model objects and preparing Models to be handed to the Views. It's the glue that holds everything together. If you're using Zend MVC, you're concerned with 2 controllers - Zend_Controller_Front and Zend_Controller_Action.
Zend_Controller_Front (which you get 'for free' if you use Zend_Layout::startMVC()) is a single point of entry for your application - it handles the raw user requests and translates URLs into an Action to call. There are various places to 'plug-in' to this to handle things like authentication and access restrictions, but, at the core it's just the 'traffic cop' at the front gate directing incoming requests.
Zend_Controller_Action is the base class for actions - essentially an Action represents something your application does (log in, list blog entries, launch an ICBM, order a pizza...), but is not directly responsible for actually doing it. The Action Controllers are pretty boring - they pull values out of forms and URLs, call a few methods on Model classes to actually perform the action and push the results out into the view. As has been said before, they're the 'glue' that holds Models and Views together.
A rough test to see if you're splitting things along the right lines is to envision a major change to your site. A visual redesign would almost entirely be handled in the Views. Moving all your URLs would change your Controllers. Converting from a web app to a GUI app would replace the views and controllers, but your model would still be mostly unchanged. If you rewrite your models, you have a whole new application.
There are several other questions on Stackoverflow that give an explanation of the MVC concept:
What are MVP and MVC and what is the difference?
What is MVC (Model View Controller)?
A very good explanation of the concept can be found on Wikipedia:
Model-view-controller (MVC) is an
architectural pattern used in software
engineering. Successful use of the
pattern isolates business logic from
user interface considerations,
resulting in an application where it
is easier to modify either the visual
appearance of the application or the
underlying business rules without
affecting the other. In MVC, the model
represents the information (the data)
of the application; the view
corresponds to elements of the user
interface such as text, checkbox
items, and so forth; and the
controller manages the communication
of data and the business rules used to
manipulate the data to and from the
model.
In relation to Zend Framework:
models are generally presented by extensions of the Zend_Db_Table class
views are presented as *.phtml files in your defined scripts folder, which are handled by the Zend_View class.
controllers are defined by extensions of the Zend_Controller_Action class.
The Zend Framework has its own very nice Quick Start/Tutorial which especially introduces MVC.
Quote from there:
So what exactly is this MVC pattern
everyone keeps talking about, and why
should you care? MVC is much more than
just a three-letter acronym (TLA) that
you can whip out anytime you want to
sound smart; it has become something
of a standard in the design of modern
web applications. And for good reason.
Most web application code falls under
one of the following three categories:
presentation, business logic, and data
access. The MVC pattern models this
separation of concerns well. The end
result is that your presentation code
can be consolidated in one part of
your application with your business
logic in another and your data access
code in yet another. Many developers
have found this well-defined
separation indispensable for keeping
their code organized, especially when
more than one developer is working on
the same application.
In as few words as possible:
model is the db
view is what you see (the page)
controller is the glue (logic)
Your models know how to access tables containing your data; your views know how to display content; and your controllers glue it together (what view do I show? what model should I use?).
I've been reading several articles on MVC and had a few questions I was hoping someone could possibly assist me in answering.
Firstly if MODEL is a representation of the data and a means in which to manipulate that data, then a Data Access Object (DAO) with a certain level of abstraction using a common interface should be sufficient for most task should it not?
To further elaborate on this point, say most of my development is done with MySQL as the underlying storage mechanism for my data, if I avoided vendor specific functions -- (i.e. UNIX_TIMESTAMP) -- in the construction of my SQL statements and used a abstract DB object that has a common interface moving between MySQL and maybe PostgreSQL, or MySQL and SQLite should be a simple process.
Here's what I'm getting at some task, are handled by a single CONTROLLER -- (i.e. UserRegistration) and rather that creating a MODEL for that task, I can get an instance of the db object -- (i.e. DB::getInstance()) -- then make the necessary db calls to INSERT a new user. Why with such a simple task would I create a new MODEL?
In some of the examples I've seen a MODEL is created, and within that MODEL there's a SELECT statement that fetches x number of orders from the order table and returns an array. Why do this, if in your CONTROLLER your creating another loop to iterate over that array and assign it to the VIEW; ex. 1?
ex. 1: foreach ($list as $order) { $this->view->set('order', $order); }
I guess one could modify the return so something like this is possibly; ex. 2.
ex. 2: while ($order = $this->model->getOrders(10)) { $this->view->set('order', $order); }
I guess my argument is that why create a model when you can simply make the necessary db calls from within your CONTROLLER, assuming your using a DB object with common interface to access your data, as I suspect most of websites are using. Yes I don't expect this is practical for all task, but again when most of what's being done is simple enough to not necessarily warrant a separate MODEL.
As it stands right now a user makes a request 'www.mysite.com/Controller/action/args1/args2', the front controller (I call it router) passes off to Controller (class) and within that controller a certain action (method) is called and from there the appropriate VIEW is created and then output.
So I guess you're wondering whether the added complexity of a model layer -on top- of a Database Access Object is the way you want to go. In my experience, simplicity trumps any other concern, so I would suggest that if you see a clear situation where it's simpler to completely go without a Model and have the data access occur in the equivalent of a controller, then you should go with that.
However, there are still other potential benefits to having an MVC separation:
No SQL at all in the controller: Maybe you decide to gather your data from a source other than a database (an array in the session? A mock object for testing? a file? just something else), or your database schema changes and you have to look for all the places that your code has to change, you could look through just the models.
Seperation of skillsets: Maybe someone on your team is great at complex SQL queries, but not great at dealing with the php side. Then the more separated the code is, the more people can play to their strengths (even more so when it comes to the html/css/javascript side of things).
Conceptual object that represents a block of data: As Steven said, there's a difference in the benefits you get from being database agnostic (so you can switch between mysql and postgresql if need be) and being schema agnostic (so you have an object full of data that fits together well, even if it came from different relational tables). When you have a model that represents a good block of data, you should be able to reuse that model in more than one place (e.g. a person model could be used in logins and when displaying a personnel list).
I certainly think that the ideals of separation of the tasks of MVC are very useful. But over time I've come to think that alternate styles, like keeping that MVC-like separation with a functional programming style, may be easier to deal with in php than a full blown OOP MVC system.
I found this great article that addressed most of my questions. In case anyone else had similar questions or is interested in reading this article. You can find it here http://blog.astrumfutura.com/archives/373-The-M-in-MVC-Why-Models-are-Misunderstood-and-Unappreciated.html.
The idea behind MVC is to have a clean separation between your logic. So your view is just your output, and your controller is a way of interacting with your models and using your models to get the necessary data to give to the necessary views. But all the work of actually getting data will go on your model.
If you think of your User model as an actual person and not a piece of data. If you want to know that persons name is it easier to call up a central office on the phone (the database) and request the name or to just ask the person, "what is your name?" That's one of the ideas behind the model. In a most simplistic way you can view your models as real living things and the methods you attach to them allow your controllers to ask those living things a series of questions (IE - can you view this page? are you logged in? what type of image are you? are you published? when were you last modified?). Your controller should be dumb and your model should be smart.
The other idea is to keep your SQL work in one central location, in this case your models. So that you don't have errant SQL floating around your controllers and (worst case scenario) your views.