20 July 2008

My take on MVC

MVC , or Model - Viewer - Controller is very popular on the web framework market. It has become one of the selling points for web based applications and framework. Everybody has or has to have it in order to beat he competition.
It seams if you don't implement the MVC pattern in your application you are not serious. And we all know that the most important thing in software development is being serious. If you are a member of a fringe developing group (PHP, Python, Perl, Ruby and so on... ) you have cerantainly being labeled as not serius as a software developer by your more serious and respectable colleagues in .NET, C++ or Java land. And they are right. Given the fact that all the big, technologically unsavy client go to them to buy software. It really matters. Its a fact of life. If you wanna develop in the big league you must be serious (and therefore program in serious programming languages and use serious developing techniques).
I've being developing with PHP for over four years now. I've started working with PHP 4 and switched over to PHP 5 when it hit mainstream. I loved the OOP capabilities it offered. In the beginning my web apps were plagued by a mirad of simple and annoying problems. Liking issues, navigational issues, code and markup mixed together, character encoding problems and so on. It got better over time, and what really made my apps better, more easier to develop and maintain was the use of the Model - Viewer - Controller design patter.
Every one and his grandmother has his take on MVC . I've developed mine, and I think I got it pretty much right. Everything revolves around one file. That file will be the single point of entrance of the application. In most cases it will be index.php since it's a natural entry point for every PHP base web site.
Beside the index.php I will create a directory structure that will consist of three directories : Contoll, Model , View. And one other file config.php for various configuration options.
It will look like this :
  • /
  • /Control
  • /Model
  • /View
    • /template
  • /config.php
  • /index.php

The code for the index. php file is this:
session_start();
session_regenerate_id();
/**
*
@author Nikola Stjelja ;
*
@copyright GPL2
*/

//Load configuration
include('config.php');


//Get the control
include('Control/control.class.php');

//Get the model
$model=Control::get_model();

//Load the page
$model->load_page();

//load the view
include('view/view.class.php');

//show the template
View::show_template($model->template,$model->data);


?>;

Each request in your application will go through this file. First the configuration will be loaded. The config.php file will contians only configuration options. It is best to set those options as constants. The the Control class will be loaded. It is a static class, e.g. it doesn't have instances. It has only one public method get_model() which will return the model object. The model object has one public method load_page() and two public proprieties template and data, which are loaded as argument to the View static class. The View class handles any templating your application has to do in order to present its content to the client requesting it. The entire entry point of our application has no more that 29 lines , it is simple and readable. It shows you exactly what part of the application does.
The beauty of it is that the application logic can become quite complex but the underlying system will remain simple to use and understand. Needless to say that the most of the work is done inside the model object. Here is the abstract Model class each model object must inherit from:
/**
*
@author Nikola Stjelja ;
*
@copyright GPL2
*/

/**
* Main application logic. This class is inherited by all Model classes.
*/
abstract class Model{
//Template file name
public $template='template.tpl.php';

//Array with the all data viewable as variables inside the template
public $data=Array('title'=>'MVC Application');

/**
* Class consturctor
*/
abstract public function __construct();

/**
* Prepares the page to be displayed.
*/
abstract public function load_page();

/**
* This method prepare super global variables for usage
*/
protected function sterilize($var)
{
$var=(strip_tags($var));
if (get_magic_quotes_gpc()) $var=stripslashes($var);
return $var;
}

/**
* Class destructor
*/
abstract public function __destruct();
}

?>

As you see the class is quite simple. It provides a simple interface that anyone can understand and use. The load_page is the main class method servers as the main class logic controller. The Control static class implement the Factory patter. It's main goal is to create the adequate model object based on the web page query. This is a very simple navigational mechanism. It allows to the developer great freedom in how to set up the site navigation. It's also very simple and short. The Control class may be extended with extra classes that check if the user is logged in or if the user accessing a resource has the right to do so.

/**
*
@author Nikola Stjelja
*
@copyright GPL2
*/

/**
* This is a static class that checks for a specific query string, and
* upon it returns the expected model object.
*/
class Control{
private static $choice;

/**
* Get the choice from the $_GET
*/
private static function get_choice(){
self::$choice=trim(strip_tags(urldecode($_GET['q'])));
}

/**
* Based on what date is contained inside the choice propriety return the
* model object
*/
public function get_model(){

//preuzmi izbor
self::get_choice();

switch(self::$choice){


//default model
default:
include('model/model.class.php');
return new Model();

}
}
}


?>

After both the Control and Model objects have done their job comes than the time for the View class to do its. It views class takes two parameters inside its show_template method. Both parameters come from the Model object, the template name and the data array. The main job the View class is to find the template file, fill it with variables . The rest is upon the template file it self. Normally the developer can implement his or her favorite templating system quite easly. But I like to stick with pure php. With discipline you can write a pretty readable template file just using ifs thens and whiles.

/**
*
@author Nikola Stjelja
*
@copyright GPL2
*/

/**
* Connects the template file with model provided data
*/
class View{

/**
* Loads and shows the chosen template
*/
public static function show_template($template,$data){
while(list($k,$v)=each($data)) $$k=$v;

//Load the template
include("templates/$template");
}


}
?>
The template is a standard php file. It receives its variables from the $data array generated by the model object.

No comments:

Post a Comment