Now: Tutorial for Web and Software Design > PHP > PHP Basic > PHP Content
> Implementing MVC in PHP: The Controller [Bookmark it]
Implementing MVC in PHP: The Controller

Implementing MVC in PHP: The Controller

by Joe Stump
11/03/2005

In the first part of this series, I covered the basics of MVC programming in PHP and created most of the base classes. In Part 2, I will be covering the controller and the presentation layer. (Parts three and four, Implementing the View in PHP MVC and Implementing MVC in PHP: The Model are also available.)

The Controller

Quite simply, the controller handles incoming requests. It uses input, in this case from the URI, to load a module and refresh/render the presentation layer. The controller for the aptly named Framework 1.0 uses a few GET arguments to figure out which module to load.

Before I get to the code, consider a possible request that the controller is going to have to be able to handle.

http://example.com/index.php?module=login

That looks simple enough. However, seeing that the code now runs inside a framework, things are not as simple as they may seem. Here is a simple list of arguments that the controller understands and what they do.

  • module defines the basic module that the user is requesting. For instance, you may choose to create a module named users that stores your code for logging in, logging out, and registering.
  • class defines the actual class the controller will load. For instance, in your users module you might have classes named login, logout, and register. If you don't specify a class, the controller will attempt to load one with the same name as the module provided.
  • event defines which method to run after the controller has authenticated the user. By default, the controller will look for and run the __default() method of your class.

A more complex example of what the controller might handle is:

http://example.com/index.php?module=users&class=login

This tells the controller to locate the module users, load the class login, and, because there is no event defined, run login::__default().

The code

<?php



  /**

  * index.php

  *

  * @author Joe Stump <joe@joestump.net>

  * @copyright Joe Stump <joe@joestump.net>

  * @license http://www.opensource.org/licenses/gpl-license.php

  * @package Framework

  */



  require_once('config.php');



  // {{{ __autoload($class)

  /**

  * __autoload

  *

  * Autoload is ran by PHP when it can't find a class it is trying to load.

  * By naming our classes intelligently we should be able to load most classes

  * dynamically.

  *

  * @author Joe Stump <joe@joestump.net>

  * @param string $class Class name we're trying to load

  * @return void

  * @package Framework

  */

  function __autoload($class)

  {

      $file = str_replace('_','/',substr($class,2)).'.php';     

      require_once(FR_BASE_PATH.'/includes/'.$file);

  }

  // }}}



  if (isset($_GET['module'])) {

      $module = $_GET['module'];

      if (isset($_GET['event'])) {

          $event = $_GET['event'];

      } else {

          $event = '__default';

      }



      if (isset($_GET['class'])) {

          $class = $_GET['class'];

      } else {

          $class = $module;

      }



      $classFile = FR_BASE_PATH.'/modules/'.$module.'/'.$class.'.php';

      if (file_exists($classFile)) {

          require_once($classFile);

          if (class_exists($class)) {

              try {

                  $instance = new $class();

                  if (!FR_Module::isValid($instance)) {

                      die("Requested module is not a valid framework module!");

                  }



                  $instance->moduleName = $module;

                  if ($instance->authenticate()) {

                      try {

                          $result = $instance->$event();

                          if (!PEAR::isError($result)) {

                              $presenter = FR_Presenter::factory(

                                  $instance->presenter,$instance

                              );



                              if (!PEAR::isError($presenter)) {

                                  $presenter->display();

                              } else {

                                  die($presenter->getMessage());

                              }

                          }

                      } catch (Exception $error) {

                          die($error->getMessage());

                      }

                  } else {

                      die("You do not have access to the requested page!");

                  }

              } catch (Exception $error) {

                  die($error->getMessage());   

              }

          } else {

              die("An valid module for your request was not found");        

          }

      } else {

          die("Could not find: $classFile");        

      }

  } else {

      die("A valid module was not specified");

  }



?>

After looking over the code, you might notice a few things. Here's a walk through the second example URI from above to thoroughly explain things.

  1. Include config.php
  2. Define the __autoload() function. Because all the classes are named in a structured manner, this function can easily include them when necessary. The __autoload() function is new to PHP 5 and provides a method to load classes dynamically. This eliminates the need to have the controller require every single library needed to function.
  3. If there is a module argument, the controller needs to start working on loading the module. The next few lines set up the defaults that I discussed earlier. Once $module, $event, and $class are defined, the controller can move on to loading the module.
  4. The next few lines have to do with loading and verifying the requested module and class. The controller loads the module's config.php and the class file, which in this example is users/login.php. Next, the controller checks to make sure the required file it needs exists and that the requested class is actually defined.
  5. Don't blink! On the next line I used the wonders of variable functions to instantiate the module. It's very important to note that the controller runs the class's constructor before it authenticates the user. Due to the class hierarchy, it would be impossible to authenticate before running the constructor. Also, note that the constructor can throw exceptions, which are new to PHP 5, and the controller will handle them appropriately.
  6. Now that the controller has a class, it runs the inherited method authenticate(), which should return a Boolean value. If the function returns true, then the controller continues running the module's event handler; if false, then the controller exits out. This would be a good place for the controller to redirect to a login form.
  7. The next few lines run the given event, which for the example is login::__default(). The event handler can either throw an exception or return a PEAR_Error, which tells the controller that something deadly has happened.
  8. Finally--yes, finally--it loads the presentation layer based on what the class has defined. By default, it uses the FR_Presenter_smarty presentation layer. You may not like Smarty, which is fine. Just create a new presentation class and use that instead. If there isn't anything wrong with the requested presentation layer, the controller finally runs the display() method, which does the heavy lifting of rendering the module. Notice how I pass the instance of the module class to the presentation layer.

For being under 100 lines of code, the controller sure does a lot! The beauty of MVC programming is that the controller is dumb to what is going on. Its sole purpose is to do simple validation on the request, load up the request, and hand off everything to the presentation layer to render the request.

Working within this structure can seem somewhat rigid at first, but once you realize how much more quickly you are able to create large applications and leverage the existing code, you can easily work around the perceived rigidity.

[1] [2] Next

[Bookmark][Print] [Close][To Top]
  • Prev Article-PHP:

  • Next Article-PHP:
  • Related Materias
    Important Notice for Apach
    Custom-Compiling Apache an
    Simplify Your Life with Ap
    Industrial-Strength Webcas
    Monitoring Apache Page-Loa
    Implementing MVC in PHP: T
    Implementing MVC in PHP: T
    Simplify PHP Development w
    Improve Your Build Process
    Important Notice for PHP D
    Topics
    Photoshop Tutorial
     

    Special Effect

      3D Effect
      Photoshop Articles
    Programming Tutorial
     

    C/C++ Tutorial

      Visual Basic
      C# Tutorial
    Database Tutorial
     

    MySQL Tutorial

      MS SQL Tutorial
      Oracle Tutorial
    Graphic Design Tutorial
     

    Coreldraw Tutorial

      Illustrator Tutorial
      3D Graphics Articles
    Webmaster Articles
     

    Domain Service

      Web Hosting
      Site Promotion
    Java Tutorial&Articles
     

    Java Servlets

      JavaEE Tutorial
     

    JavaBeans Tutorial

    XML Tutorial&Articles
     

    XML Style Tutorial

      AJAX Tutorial
      XML Mobile
    Flash Tutorial&Articles
     

    Flash Video

      Action Script
      Flash Articles
    OS Tutorial&Articles
     

    Linux Tutorial

      Symbian Tutorial
      MacOS Tutorial