The MVC Pattern and PHP, Part 2

Tweet
This entry is part 2 of 2 in the series The MVC Pattern and PHP

The MVC Pattern and PHP

Welcome to part 2 of this two-part series discussing MVC and PHP, where we’ll discuss some of the considerations one must make when using an MVC architecture. If you’ve come straight to this article without reading part 1 first, I encourage you to head back and have careful read as this one will assume that you’ve read and understand everything it discussed. With that in mind, let’s get started!

Routing and URLs

Although MVC, in theory, should work flawlessly in all forms of computer programming, incorporating MVC on the web with PHP can be a bit tricky. The first problem is with URL routing. URL routing is an aspect that was never considered when MVC was created, and so as the Internet evolves and develops with the expansion of technology, so must the architecture patterns we use.

So what options do we have for solving the URL routing problem? One solution is to attempt to preempt any URLs that your site or web app needs, storing them in permanent storage along with information about which Model, View, and Controller to load for each page or section. The system then gets the URL requested by the user and loads the specific components assigned for that page and gets to work. This is a perfectly feasible solution if you are creating a portfolio site or a static website, which doesn’t rely on dynamic URLs. For example:

<?php
$page = $_GET['page'];
if (!empty($page)) {

    $data = array(
        'about' => array('model' => 'AboutModel', 'view' => 'AboutView', 'controller' => 'AboutController'),
        'portfolio' => array('model' => 'PortfolioModel', 'view' => 'PortfolioView', 'controller' => 'PortfolioController')
    );

    foreach($data as $key => $components){
        if ($page == $key) {
            $model = $components['model'];
            $view = $components['view'];
            $controller = $components['controller'];
            break;
        }
    }

    if (isset($model)) {
        $m = new $model();
        $c = new $controller($model);
        $v = new $view($model);
        echo $v->output();
    }
}

Our URLs would look like this:

example.com/index.php?page=about

or

example.com/index.php?page=portfolio

The example MVC system loads the specific Model, View, and Controller set for the requested page. If the URL parameter is “about”, then the About page will be displayed. If the parameter is “portfolio”, the Portfolio page will be instead.

The is a basic example of static routing which, even through it’s very simple to set up, comes with some drawbacks. One of the most obvious drawbacks is the fact that scalability becomes much harder, as the breadth of your site is constricted to the hard-coded array of pages.

Another option is to open up the assignment of your Model, View, and Controller classes and let the URL define these parameters. In the static routing example, we simply pulled the class’ identification from an array, which in turn acted as routing data coming from our permanent storage. Replacing the array with elements turns our static routing into dynamic routing.

Despite the fact we pulled a key for each association in the array with a URL variable, the relationships with corresponding classes were already predefined; we couldn’t mix and match between the values in each key with static routing. But why would we even want to do this? Well for starters, we wouldn’t have to hard code each section of our system. We can create sections or pages just through creating a Model, View and Controller relationship. For example:

<?php
$model = $_GET['model'];
$view = $_GET['view'];
$controller = $_GET['controller'];
$action = $_GET['action'];

if (!(empty($model) || empty($view) || empty($controller) || empty($action))) {
    $m = new $model();
    $c = new $controller($m, $action);
    $v = new $view($m);
    echo $v->output();
}

Our new URL would now look like:

example.com/index.php?controller=controllername↦model=modelname&view=viewname&action=actionname

The action URL variable tells the system which function in the Controller to execute. It is important to remember that when this function passes data to the Model, it passes a piece of data to the Model that will in turn indicate which View and View Action to load. This can be the action URL variable, but it can also be separate, or data collected by the Controller. Remember to never allow the Controller to load or directly pass data to the View; it must only interact with the Model and the User’s inputs.

Both approaches have their pros and cons, with static routing being more stable, quicker to implement, and allowing developers more control over the system, and with dynamic routing allowing us to create a more effective system where there is huge potential for scalability and portability.

Dynamic routing can, however, place more responsibility on the Controller than static routing, which can be seen as altering the traditional MVC pattern. Nevertheless, if dynamic routing is implemented correctly and effectively, is can make the Controller more desirable within the system compared to using static routing.

Adding a Front Controller will allow your system to dynamically load sections, depending on what you want it to load. Alejandro Gervasio has written a fantastic 2-part article about the Front Controller pattern, which touches on ideas of using a Front Controller with elements of MVC. I highly recommend this for anyone wishing to know more about Front Controllers and MVC. I also recommend a quick visit to Tom Butler’s site as he has an article which looks at implementing the Front Controller into his “1.1 Controller:View” relationship, ideal for those looking to develop a true dynamic routing solution into their MVC system.

DRY (Don’t Repeat Yourself) & Templates

One of my main arguments for using the MVC pattern is the aim to make your overall system as organized as possible. The most obvious way to do this is to reduce the amount of opportunities to have multiple instances of the same code. Any developer will agree that the worst thing to find in any application is repetition of the same code. The practice of keeping your code streamlined and using reusable components as much as possible is know as the DRY philosophy – Don’t Repeat Yourself.

The DRY principle dictates that “every piece of knowledge must have a single, unambiguous, authoritative representation within a system.” The aim of DRY is to increase and explore every possible avenue open to developers to make their system as dynamic and optimized as possible. DRY principle implies that, if you need to write the same piece of code in many places, instead of repeating the code at these places, create a separate method and use it wherever required. This allows the system to become more optimized and introduces the possibility of caching within our systems to help improve the overall run time.

A correct implementation of DRY would imply that changing one element of the system does not change unrelated elements, which makes DRY an important principle to work to when developing with MVC patterns.

Templates

The word “template” might raise a few questions for those who have seen MVC web frameworks before, as most people lump the template part in with the View. As we’ve discussed before, this is incorrect if you wish to stick with the traditional MVC pattern. Ideally, you would have the View dealing with the data crunching and processing after collecting the data from the Model. Therefore it only makes sense for your View component to select a template and pass the data from the View into that template. That way it is ready to be displayed using a block code layout, or with an echo, print, or any other outputting code in PHP. Whichever of those methods you choose to use, the main thing to remember is that your data MUST be at a state of readiness that you only need to print the data in the template. If you are doing other data processing or crunching in the template your setup is wrong, and most likely, the MVC setup is incorrect.

Here’s a quick example of your view loading a template and pushing data to it:

<?php
class Model
{
    public $tstring;

    public function __construct(){
        $this->tstring = "The string has been loaded through the template.";
        $this->template = "tpl/template.php";
    }
}
<?php
class View
{
    private $model;

    public function __construct($model) {
        $this->controller = $controller;
        $this->model = $model;
    }

    public function output(){
        $data = "<p>" . $this->model->tstring ."</p>";
        require_once($this->model->template);
    }
}
<!DOCTYPE html>
<html>
 <head>
  <meta charset="charset=utf-8">
  <title>The Template name</title>
 </head>
 <body>
  <h1><?php echo $data; ?></h1>
 </body>
</html>

In addition the template is being passed through the model, which in principle can allow for dynamic assignment of templates depending on what each particular View is meant to be doing. This method of templating allows MVC systems to be expanded upon efficiently and confidently, while giving us the option to split the back end development from the front end development; an original goal of the MVC pattern.

Conclusion

The MVC pattern was a game changer when it was first used for desktop programming. It was, and still is, a highly debated topic between developers with regard to interpreting certain scenarios when developing with it. The debate becomes even more intense when you add PHP and the web into the mix, which is a fantastic sign that more and more developers are becoming focused on improving development disciplines for PHP.

MVC is a personal favorite because of its encouragement of separation between the different processing parts, and the opportunity of separation between the front end and the back end. I implore anyone who hasn’t developed with MVC before, especially in PHP, to sink their teeth into this wonderful development pattern; you will not be disappointed.

Comments on this article are closed. Have a question about MVC Patterns and PHP? Why not ask it on our forums?

Image via Fotolia

The MVC Pattern and PHP

<< The MVC Pattern and PHP, Part 1

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://- koos

    Thanks for sharing your thoughts. I was wondering: How does JavaScript come into play? In my apps there is quite some PHP involved, but also quite some JavaScript, which e.g. creates a table like http://datatables.net. Do you think it is possible to stick to the MVC using this approach?

    • http://www.callumhopkins.com Callum Hopkins

      Hi Koos,
      Thanks for your comment. The stand point on Javascript really depends on wither it’s job purely for interaction, or for data handling. Your PHP model isn’t just the file which saves to the database, so your PHP model can be configured to collect the data from the controller, pass it to your Javascript module for saving the data permanently, and then have the Model request the data from the Javascript system to pass to the View component. The examples in the article are based on pure PHP MVC systems, rather than ones with Javascript implementation in mind.

      Thanks

  • http://www.psinas.com Martin Psinas

    From the first article: “The Controller is also only connected to a single View and to a single Model, making it a one way data flow system.”

    How do you approach a situation where you need to connect to more than one Model in a single request? For example when submitting a contact form, I might have one Model that connects to a mail server to send mail, and another model to store / retrieve any errors that occur.

    From this article: “the main thing to remember is that your data MUST be at a state of readiness that you only need to print the data in the template. If you are doing other data processing or crunching in the template your setup is wrong, and most likely, the MVC setup is incorrect.”

    Do simple loops or IF statements qualify as data processing / crunching, or is very basic logic acceptable in templates?

    • http://www.callumhopkins.com Callum Hopkins

      Hi Martin,
      You will be looking at using a front controller to manage multiple small MVC patterns, making your overall system modular allowing each piece to be edited, but not wholly relying on another. Sounds like you’re moving on more advance topics within MVC, where as this article is really an introduction and the bare bones to the traditional MVC method. I would recommend pushing a MVC specific book, or checking out Tom Bulter’s blog (http://r.je/) as he address some more complex issues you may come across soon. Tony Marston’s site (http://www.tonymarston.net/php-mysql/model-view-controller.html) also has some great articles on MVC in PHP. Good luck and thanks for being interested in my article series! :)

      Thanks

      • http://www.psinas.com Martin Psinas

        Another question… You describe the Model as being “blind”, which leads me to believe (correct me if I’m wrong) that the Controller is the most appropriate place for input validation and the like; so why do you call the template from the Model which should have no knowledge of what is being done with the data?

        • http://www.tonymarston.net Tony Marston

          No, the controller is *NOT* the most appropriate place for input validation. This should only be done within the model, which should make the controller aware of any validatiuon errors so that it can take the appropriate action.

          The model is “blind” insofar as it returns its data in response to a particular request, but is has no knowledge of how that data is going to be handled afterwards. It may be displayed in an HTML form or a PDF document, or written to a CSV file.

          • http://www.xoogu.com/ Dave

            It would seem to me then, that in a situation where the goal is simply to update a database record, such as the posting of this comment, then the controller does essentially nothing? The Model would process the comment data and insert it into the database if okay. Then the view would retrieve the success or error status from the Model for outputting to the page?
            In a case where email subscription to comments was activated, then the controller would have something to do (send email if comment was was approved).

            Is that correct?

    • Chris Emerson

      I use ‘blocks’ in my templates, where each block is a piece of code that can be repeated 0 or more times. That covers conditionals and all types of loop. The template doesn’t need to know which it is, and the view is responsible for telling the template to output blocks as necessary. PHPXTemplate uses this, and I adopted it for my own templates as well – I really like it.

      Having the tag in the view is pretty horrible in this example though – why isn’t it in the template? Also, I’d like to ask the same as Martin – What if I’m using 2 models in a request? This pattern doesn’t seem too flexible to deal with that situation.

      • http://www.callumhopkins.com Callum Hopkins

        Hi Chris,
        You make a good point about the tag in the vie and the use of code block. The reason why I didn’t go into using code block in the template is that in itself is another topic and would steer the article into a different direction. Code block is something that can make a huge improvement when using templates, so I’m un surprised with your passion for it ;)

        As for the multiple MVC systems, you can connect a controller to two different Models, but the article as written to keep things as simple as possible. The article was written an introduction to using MVC patterns in PHP and every question may not be answered in the article, which I apologise for.

        Thanks

  • http://www.psinas.com Martin Psinas

    Upon further reading, and again someone please correct me if I’m wrong, but everything described as “what NOT to do” in these articles in regards to MVC are actually principles of a different design pattern all together, namely HMVC. In which case, these aren’t necessarily confused, inaccurate, or bad practices, but something else entirely.

  • http://keryx.se/ Lars Gunther

    Hi
    Having taught PHP to student for a long time I know that they will pick up on the parts of examples that are non central and half baked and use it nevertheless. This article would benefit from two big notes about such half-finished issues.

    1. The URL is for the user, not the system. Thus, using query parameters to chose modules in PHP is bad usability. I do realize that this is outside the scope of the article, but as I said, unless explicitly told, my students would not be discouraged from picking up EVERY part of an article like this.

    2. Unfiltered use of GET-parameters. In the specific example it does not matter, because there is a white list in the arrays, but as complexity grows, that might not be the case. And as Doug Ccrockford says, one shoukd use the pattern that always yields the safest results. So instead of reading the superglobal array $_GET, it would be better to use the filter_input function.

  • http://www.tonymarston.net Tony Marston

    I’m afraid that I have to disagree with two points made in this article:

    (1) URL Routing.

    The idea that URL routing has anything to do with the MVC pattern is completely wrong and totally irrelevant. The fact that you are also promoting the use of a front controller shows that you have forgotten that PHP was designed to use the web server (typically Apache) as the front controller as it can automatically route the request to the designated page controller without the need to go through a monolithic single point of entry. Read Rasmus Lerdorf’s comments on this very issue in http://toys.lerdorf.com/archives/38-The-no-framework-PHP-MVC-framework.html

    Thus instead of this URL :

    example.com/index.php?controller=controllername&amp;map;model=modelname&amp;view=viewname&amp;action=actionname
    

    I would have the following:

    example.com/customer(update).php
    

    The script customer(update).php would contain the following:

    &lt;?php
    $table_id = ‘customer’;    // identify the Model
    $screen = ‘customer.detail.screen.inc’;  // identify the view
    require(‘std.update.inc’);    // activate the controller
    ?&gt;
    

    Every page in the application should have its own page controller, and it makes more sense to go straight to the page controller instead of getting lost in a front controller. It also makes it easier to add new pages if you don’t have to make the front controller aware that a new page has been created.

    (2) You should aim for a 1:1 relationship between controller and view.

    This idea is restrictive, therefore wrong. Although a controller should access only one view, it is possible to have a single view shared by several controllers. In my framework all HTML views are generated from XSL stylesheets, and I can share the same stylesheets with several controllers. Being able to create code once that can be shared by multiple components is what the DRY principle is all about, something which the author of this idea seems to have forgotten.

    On the subject of maximizing reusability, my own framework uses a fixed set of page controllers which are not tied to any models, only views. Thus a single controller can be used with any model as it does not need to know any of the properties held within the model, only its methods. As all the class methods are inherited from a single abstract class this is a perfect example of how to use polymorphism to maximum effect. So with 40 reusable controllers, 17 XSL stylesheets and 250 table classes my main application has over 1700 user transactions.

  • http://noondreams.com Mohammad Rahmani

    In this article we were not told why in View constructor we tell the View the controller is, I have not seen where the $controller is used in View

  • Duc Huynh

    Thanks for sharing! It’s really helpful for me :)

  • http://bitflop.com KNL

    Hi.

    I read this article and the first thought that came to mind was, ‘Oh no! Not again!’, another PHP article about the MVC pattern that gives the readers the wrong impression about what the MVC pattern is!

    Just because everyone (most frameworks) is doing the MVC pattern in a particular way doesn’t mean that that is the way it must be!

    First of all you state, “URL routing is an aspect that was never considered when MVC was created”, and this shows that you actually has fallen into the same trap that everyone else seems to be falling into these days.

    Let us get the MVC pattern right, once and for all, it is a pattern, a theory. It can be implemented in just about thousand different ways!

    It can be implemented in procedural programming, in object oriented programming, in functional programming, and again in many different ways.

    There is no actual representation of the controller, the model, and the view. You have to design these parts of the system. Which files fits into what task, ie. controller, model, or view, depends on what you make those files do and how they interact with eachother, the users, and the underlining technology.

    Just to make my point: You can have 50 entry points in your system with the most obscure URL structure and STILL implement the MVC pattern – as long as you separate the correct parts from eachother.

    Patterns are becomming too dominant in PHP programming these days and people misunderstand they usage.

    Patterns are not a set of standards to be followed so that every single problem must be spoon fet by force to some particular pattern.

    That is what people are doing these days, they actually force problems into patterns rather than thinking about the best solution to a problem.

    In 9 out of 10 situations patterns results in excessively complex solutions that are ineffective and extremely hard to understand.

    That said, nice article about ONE way, out of many, to do the MVC pattern in PHP.

  • Brian

    Another important PHP example correcting many of the misunderstandings about MVC: http://r.je/mvc-in-php.html

  • Mathieu

    Awesome article. Can you suggest any good books on MVC in web development?

  • Bogdan