PHP
Article
By Callum Hopkins

The MVC Pattern and PHP, Part 2

By Callum Hopkins

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&map;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.

--ADVERTISEMENT--

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

More:
Recommended
Sponsors
The most important and interesting stories in tech. Straight to your inbox, daily. Get Versioning.
Login or Create Account to Comment
Login Create Account