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.
Related
In a MVC application it is easy to understand how the Controller extracts data from the request and updates the Model layer but I am a bit confused as to how a View is supposed to retrieve data from the Model layer when the View does not know about the request?
For example if I go to
http://www.site.com/product/view/428
I route the URL and I dispatch the request and I end up in the Controller. Nothing needs to be done in the Controller(I think?) and when it gets to my View I need the product ID but the View should not be extracting data from the Request so what do I do?
Thanks.
There are two approaches for handling this and both actually would indicate that controller in this case a significant role to play.
The fabled ways of ancients ..
The first option for resolving this issue would be adhering to classical MVC as close as possible. This kinda relates to what people mean, when they say 'you cannot do classical MVC for web'. In classical MVC the view observes model layer. And that part can actually be implemented.
If that's the approach you want to take, then you will have to learn about Observer (1), (2) pattern and how to use it in PHP (1), (2). Though there has been some push for moving away from Observer pattern.
Since I have not explored this approach in any meaningful way, I will not give any examples.
The puny trail from this decade ..
If you read Fowler's "GUI Architectures" article, you might notice the part which state that views and controllers form pairs. When applying the ideas of MVC to context of web, there are ways to benefit from it in the bootstrapping stage of application.
FYI : I'm not anymore so sure, that you can call this way "Model2 MVC". There are some significant inconsistencies. I'm gonna poke more at this nagging suspicion some more, when I'm bored.
Consider this fragment:
$router->route( $request );
$resource = $request->getParameter('controller');
$view = new {'Views\\'.$resource}($serviceFactory);
$controller = new {'Controller\\'$resource}($serviceFactory, $view);
$method = $request->getMethod(); //post, get & etc.
$command = $request->getParameter('action');
$controller->{$command.$method}($request);
$view->{$command}();
echo $view->render();
The controller fragment in your example URL would be "product" and action would contain "list". I left those names instead of resource/command pair to make it less confusing.
If you start out with a premise that views and controllers are paired to some extent (whether the pairing is cohesive or not is debatable), then you can express it by using same names. This also lets you move the initialization of view out of controller.
Another aspect which is encapsulated in the fragment above is the fact that, due to the request-response nature of web, every operation in controller will require an accompanying one in the view. And similarly to how you have actions in controllers, you can also opt to call specific, route-related methods in the view. That would remove some boilerplate conditionals from views and let you better organize the whole thing (this is kinda the "highly subjective bit").
So .. how do you turn /product/view/428 request in something visible on site?
As you probably know, the responsibility of controller is to alter the state of model layer, which in this case might code something like this:
public function getView( $request )
{
$warehouse = $this->serviceFactory->provide('warehouse');
$warehouse->chooseItem( $request->getParameter('id') );
}
The your view instance uses the primed service from model layer to acquire data:
public function view()
{
$warehouse = $this->serviceFactory->provide('warehouse');
..
..
// retrieve data about sales for product with ID: 428
$something = $warehouse->getSalesFigures();
..
}
The exact implementation of view will depend on how far off deepend you are willing to go. Two most reasonable options would be:
fetch data, inspect it and if necessary choose templates and dump data into them
use a set of presentation objects to work with model layer and based on the result bind those presentation objects to ant number of templates
my 2 cents
In MVC, A controller "controls" the flow of information between the model, where the information is "stored," and the view, where it is displayed. Therefore, the controller handles all the changes of information and interaction with the models and then sends the necessary information to a view that then displays whatever information was requested/changed/etc.
MVC is all about the separation of responsibilities.
Models are responsible for storing and modeling the application's data.
Views are responsible for displaying information to the user.
Controllers actually have multiple responsibilities:
Deciding when to Create new instances of a Model.
Deciding which instances of Models to Read and passing them to the appropriate View.
Deciding which data in a Model instance needs to be Updated based on data passed back from a View.
Deciding when to Delete no longer needed instances of a Model.
In other words, Controllers sit between the Models and Views and do all the business logic for an application, including figuring out which CRUD operations need to happen... although the actual CRUD operations are usually part of the Model itself.
A better name for MVC would probably be MCV to stress how the Controller sits between the Model and View.
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.
I was a flat php programmer for past 2 years. Now I want to move to MVC architecture and so I am using codeigniter which looks very simple to start with. I want to know some of the best practices out there as I go developing in codeigniter.
I have a controller called building, a model called building_data and a view called building_view. Now i want to display list of building by checking lot of conditions. I am doing the following in flat PHP
Get the list of buildings from database
Split the result based on certain criteria A, B, C
Display the result in section - A, section -B, and section-c as the HTML output.
Now in MVC I am doing the following
Get the list of building in the database on building_data (model)
Store the result from building_data in a $data array of the building controller
Split the results based on criteria A,B,C in building_view and output the HTML (can i do the condition based classification of data (without using mysql queries) in view ? !My actual question)
Am I doing the right thing here without violating MVC architecture rules ?
MVC is a design pattern. Not an architecture.
But, if you are looking to learn best practices or MVC, then CodeIgniter is the wrong choice. It is filled with bad and outdated practices (PHP4 code fragments, global state and many other issues), and is not implementing anything even close to MVC pattern. It is more like a bad Rails clone for PHP.
Views are supposed to be objects, and not dumb templates. Your controller should tell model layer which building the user has selected, and then view acquires the details about current building and decides how to represent it all.
In proper MVC implementation, views are instances which contain presentation logic. They acquire information from model layer and then choose which templates to use for rendering the response or even if a HTML response is necessary. Maybe user actually requested data in JSON or XML format. Or maybe the only response, that view needs to send, is a HTTP header.
Also you should be aware that you cannot implement classical MVC pattern in web application (or at least it is extremely difficult and entails use of sockets and persistent model). Instead we use MVC-inspired patterns. The main difference between them is way how View gets to the information from Model layer.
in MVP and MVVM patterns the view is passive and receives data through controller-like structure (presenters or viewmodel, perspectively).
in Model2 MVC and HMVC patterns the view is active, it requests information directly from model layer.
Also there is third group: Rails-like implementation. It replaces model layer with collection of ActiveRecord based ORMs, pretend that view is a template, and "controller" is combination of presenter and view responsibilities.
Given the URL http://www.example.com/products.php
products.php contains:
<?php
include ('model.inc');
$controller = new Controller;
class Controller
function __construct()
{
$model = new Model;
$this->model->model_methods();
include ('view.inc');
}
}
?>
model.inc contains:
<?php
class Model {
// methods that return data
}
?>
view.inc contains:
<html>
<head>
</head>
<body>
<!-- html plus php output -->
</body>
</html>
So products.php creates the controller. The controller creates the model, figures out what to do and manipulates data only through the model's methods, and finally turns things over to the view. The only php in the view is to output data or to loop through an array to output data.
I've been playing around with a few lightweight php frameworks that implement MVC, but so much of the magic gets done backstage that I don't know if I finally get it or not. :)
Have a look at this MVC article on Coding Horror.
If you think about what a model represents - a "model" of the data, or a subset of the data - and about what the view represents - a particular "representation" of the data - then it's easy to understand that these two entities require something to route the information between them. Hence, the controller. The flow should be M -> C -> V
A good test if you "understand" MVC (and thus, if your application is MVC) is "Can I skin my application?" If you can think of an easy way to apply different skins and styles to your data seamlessly, then you have succeeded in separating the model from the view, and your controller is effective at what it does.
Although I don't know how it's actually implemented, I'd argue that StackExchange is a great example of the MVC idea. There are multiple sites dealing with multiple topics, but they all have very similar kinds of "models" - very similar data. The presentations - the views - are free to change as they please, and the controller is there doing all the logical heavy-lifting. This may be kind of a contrived example, but I think it works conceptually, if not technically.
Personally, I think your Controller is responsible for too much. Instantiating the Model and View inside the Controller "feels" wrong. The Controller should only be responsible for getting data from Model and giving it to View. Right now the Controller is responsible for creating the Model AND it is effectively acting as the View by including the HTML.
The important part here is that each object has, ideally, a singular responsibility.
Model = the data holding your app (this is really a layer instead of an object)
View = the final output sent to the user
Controller = give stuff to View from Model
I recommend you create some kind of "front controller" type object that handles the appropriate instantiation of objects and is the one responsible for setting up all the different pieces.
Ah, ok, but how does the controller "give" the data to the view?
Well, this is really gonna be dependent upon the precise architecture your particular implementation uses. MVC goes far beyond a simple design pattern and can be interpreted in a variety of ways. I prefer something that looks like...
class Controller {
protected $viewData = array();
public function index() {
$data = $this->Model->getData();
$this->giveToView('data', $data);
}
public function getViewData() {
return $this->viewData;
}
protected function giveToView($key, $value) {
$this->viewData[$key] = $value;
}
}
So, the Controller is still getting the data from Model but now instead of including a view file we just store the data and let a different class take care of actually rendering the output.
class View {
protected $viewData;
public function setViewData(array $data) {
$this->viewData = $data;
}
public function renderViewFile($filePath) {
// from example the variable $data is now available in this scope
// to include the $filePath
extract($this->viewData);
include $filePath;
}
}
Obviously this is a simplified example but the basic premise stays the same.
The idea of the MVC is to separate your application logic (business logic, business tier, middle layer or middle tier), input (url, post data, get data) and output (UI - the html in your case).
It is an determined as architectural pattern (software architecture). It is not matter of code but of ideologic for building applicaions.
Read here: MVC in Wikipedia
I would prefer CodeIgniter - a very static collection of functions, some named Model other Controller and there are Views plus a lot of utilities, allowing you to concentrate on the application logic and the layout, without loosing coding freedom in PHP (seems you use PHP). Unless you find out that it's not fitting, but that can happen with any framework.
Yes. This is more or less MVC. The basic gist of MVC is as follows:
Controllers tie your models and views together and normally take care of passing model data to the view.
Models handle your business logic.
Views handle presentation and presentation related logic.
I'd definitely take time to learn PHP MVC framework such as Kohana, Lithium, Symfony, or Cake as they all provide a ton of utilities to make your life easier. They can also handle automatic routing wich makes your URLs cleaner, and helps abstract URLs from their direct connections to controllers.
Kohana: http://kohanaframework.org/
CodeIgniter: http://codeigniter.com
Lithium: http://li3.me/
Symfony: http://www.symfony-project.org/
Cake: http://cakephp.org/
Not quite yet!
The /products.php portion is generally abstracted. The file name is matched in a router during execution, which matches it to a corresponding controller. In this case, you could have a Products controller by name, but you could match (via routing) a things.php request to the Products controller.
There's generally some more execution/initialization "magic", which calls the pertinent model/view based on the request - for example, it would take /products.php, change to Product, and look for a model, controller, and view named Product.inc
Yes, that is the essential basis of the MVC pattern. The controller can be thought of as the brain which figures out what action to take. Depending on that action, it may communicate with models to get the necessary data to render the view. It then makes the necessary data available to the view and renders the HTML for the browser.
MVC at it's most basic definition requires that you split the navigation logic, the data logic and the presentation logic into 3 parts. There is no special structure to observe as long as you have the parts split so that you can easily interchange and isolate your code.
Obviously, there are many more topics to cover if you want to be an hardcore MVC layout.
For example
Splitting your application into folders called controllers, views and models
Creating a good data layer to simplify your models as much as possible
Integrating a helper/widget logic so you can reuse visual components
Integrating a routing engine with mod_rewrite to create clean urls
Those are just a few of the items you should cover to get a real good MVC layout. But then again... MVC is a design pattern, it's a way of doing things without being something totally concrete or concise.
I need help clarifying the correct structure and process flow for an MVC application in PHP.
I think I've got the concept round the wrong way because currently most of my processing is done (or at least initiated by) the Views. -- I kind of inherited this way of thinking from the company I'm working for, but now I'm not sure that they are understanding the MVC model correctly!
Having looked at it again I think that the proccess should be as follows (very basicly):
The users actions are sent to the Controller
The Controller process those actions using any Models required
The Controller then instantiates the relevent View and passes the required data to it
The View renders the page to the user
I'm also having some difficulty deciding wether the view should even have any real functionality in it or not.
i.e. Is it just a wrapper to hold the page data and load the required template files (header, page, footer etc.), OR should any functions to do with rendering data (i.e. preparing HTML and outputting HTML) be in the View?
Another question is does the controller 'hand over' to the model and have nothing to do with the actual DBconn (so that the Model acts like a Bouncer on the doors of the DB nightclub, and we're not on the list) OR does the controller 'own' the DBconn and simply lends it to a model when it needs it?
I'd really appreciate any help and advice anyone can offer.
Thanks
edit -- I found this helpful!
I'll answyer to your two last questions:
1) The Views should have basic output capabilities, for example escaping values to avoid security issues or display a html table starting from a list of objects. Another responsibility could be the translation of labels and other constant values (for example you could have $this->_('Your label') where function _($val) is a function included in all your view classes that translates the strings starting from a csv file).
2) Depending on the complexity application, you could have two sub-layers in the model layer. The upper layer is the classic model with the functionality of your entities. The lower level is the resource model class associated that performs the db operations. You could also have a single layer with your models that implements the DAO pattern. Anyway, the controller shouldn't have nothing to do with db connection.
Your bulleted assumptions are correct :). The main idea behind MVC is loose-coupling and interchangeability between components.
To answer your questions:
The view should be presentational only, so iterating through a list of models in the view and outputting them there is fine, but processing data in the view is not.
The model should not assume anything about the controller and the view. It should be easy for you to switch between a model that draws data from a database to one that draws data from another type of data source and this should not determine changes in the Controller. Fabrizio is right, you should check out the DAO pattern for an example on how to do this.
I really recommend taking a look at frameworks that implement MVC to see how they do it. Especially Spring - even if you're not a Java person, the implementation is very clean -, Rails, Symfony. For something more exotic take a look at Django.