Contact me mate!

close
  • captcha




MVC, XSLT and other animals

Sun, 29 Mar 2008

1. What's MVC? ... and XSLT?

The MVC architectural pattern is a smart and bright way of developing web-based applications. The acronym MVC stands for Model, View and Control: these are the three components that, according to the pattern, every application can (and should) be divided into. I would actually state that MVC is "the ultimate" way of developing apps but since IT is such a fast-growing/evolving discipline, I won't dare being so bold and just say that it is certainly a topic every good developer should spend some time on.

This article will try to briefly expose the basics of the MVC pattern and put forward an alternative template management system based on the duo XML/XSLT. Many MVC implementations in php are actually quite fuzzy in the way they manage the Views layer. Most of them partially fail in separating the markup from the programming language and there are often some residual bits of php code here and there (in the view files) that really annoy me a lot! ;-(

As I'll show you in a while, it is absolutely possible (and wise) to keep the two things clearly distinct and obtain a complete separation of presentation from logic. OM!

The goal of MVC pattern is, as stated above, to identify (divide and develop separately) the 3 layers we have briefly outlined. Let's try a simple definition for each of them:

  1. Controller: this is the application's layer which is responsible for the interaction with the client (and the human being who's using the client ;-). It is the means by which the user can alter the state of the application and obtain the results he is using the application for. The Controller layer is therefore a kind of "conductor" that decides, on the basis of the client's request, what piece of the Model layer (point 3 in the list) to trigger in order to perform the requested data manipulation. Also it is responsible for deciding what View (see next item in the list) to involve in order to physically create the interface that is going to display the results.
  2. View: a View is basically the scaffold where all the data (corresponding to a certain state of the application) are displayed. It goes without saying that every state of the application (or every set of similar states) should have its own View by which to show the data. Usually a View is not created using a programming language but rather some sort of markup (description) language. Here the aim is to define how the data will be formatted and what their spatial organization will be. In terms of web-based applications, a View is often an HTML (+ CSS and JavaScript) file that is used by the Controller to merge it with the data given back by the Model layer.
  3. Model: this layer is responsible for manipulating (saving/erasing/editing/transforming) the data in the database. Actually the database is not a prerequisite of MVC but most of the time apps end up using a database to store the data and therefore the Model has been historically identified with the layer in closest contact with the db. Anyway it's worth noticing that in a non database-driven application, the Model would still play a very important role and that would be performing all the computations requested to obtain the results expected by the Controller.

It's also probably worth noticing that the 3 layers correspond to as many differently skilled developers. A pure php developer will actually be responsible for the logic of the application (Controller layer), a more db oriented (php) developer will take care of the implementation of all the Model layer (db structure and performances as well as data tranformations/alterations) and finally, (which is actually my favourite!) the front-end developer will produce and maintain a highly responsive, accessible, usable and cool interface (View layer). All in all a really nice and friendly environment don't you think? Keeping the 3 levels separate also corresponds to allowing the 3 developers to work freely in their relating environments without running the risk of editing by mistake pieces of code that are outside his/her jurisdiction! It sounds good, doesn't it?

Ok! We have briefly identified the most important elements of the MVC pattern, well done. The next step will be the implementation of a very silly application that allows the user to:

Basically it will be a 2-states application (either "articles list" or "chosen article") that will allow us to have a closer look at each of the 3 components forming our MVC application. Let's start with the front controller then: the pumping heart of our project!

2. The front controller and the sub-controllers

All the sub-controllers in our application will be coordinated by what's commonly called "the front controller". Such component decides what sub-controller to evoke on the basis of the input sent to the server by the user (in PHP this information is conveied via the superglobal array $_REQUEST). The front controller is therefore the entry point to our application as all the requestes are processed by and aimed to this piece of code. Here's an example of a possible front controller:

class frontController { static function dispatch() { // it identifies the action parameter if (!$_REQUEST['action']) { $action = 'default'; } else { $action = $_REQUEST['action']; } // it dinamically composes the name of the action $actionClass = $action . 'Action'; $actionInstance = new $actionClass; $actionInstance->exec($_REQUEST); } } // let's run the static method dispatching the request frontController::dispatch();

As you can see the class is defined and the static method "dispatch" is run straight away. This method composes the name of the sub-controller at runtime (using the input $_REQUEST['action']), instantiates it and finally fires its exec method (which must be defined in each sub-controller class). Ideally the piece of code above should be placed in the file index.php. Clearly the class frontController should be able to access all the sub-controllers (each of which is gonna be a class), so before instantiating the front controller it is essential to run a require_once that points to the file where all the sub-controller classes are stored. Something like this should do:

require_once("path/subControllers.php");

Ok we have the dispatcher now. Let's first have a look to the sub-controller managing the "articles list" state and then move on to the "single article" one.

3. Let's create the Articles List

As we said each of the sub-controllers must be a class and have a public method called exec. Note that this sub-controller will be called defaultController and it will be therefore triggered by simply pointing to index.php without passing any other additional parameters (in fact no specific article needs to be identified). Here we go:

class defaultAction { public function __construct() { // the constructor will automaticly load the // file containing the models require_once("path/Models.php"); } public function exec($req) { // it instantiates the relating model ... $db = new defaultModel(); // it fires the method returning the data (XML format) $XML = $db->getXMLData(); // it creates the xml document $xmlString = new DomDocument(); // and fill it in with the xml-like string obtained from the db $xmlString->loadXML($XML); // it creates the XSL doc $xsl = new DomDocument(); // and loads the XSL file into the doc just created $xsl->load("views/defaultView.xsl"); // let's create the XSLT processor $proc = new XSLTProcessor(); // and import the xsl into the parser $proc->importStyleSheet($xsl); // finally we perform the transformation $HTML = $proc->transformToXML($xmlString); echo $HTML; // I also print a commented out version of the xml data // which helps the front end developer to figure out what the data // he can use in the xst are (and what is the xml structure of such data). echo "<!--\n\n"; echo $XML . "\n\n"; echo "-->"; } }

The class includes the file containing the Models (we will talk about this layer in a while), instantiate the relating Model and run the getXMLData method in order to obtain the list of articles. The interesting bit here is the format the data are given back in and what we actually do with them. As the name of the method suggest (getXMLData) the data are gonna be formatted in XML. That is the starting point from which we will be able to implement our brand new XSLT-based template engine. I won't go into many details about the sub-controllers but, as you can easily figure out flipping through the code, I have created an xml document and populated it with the string obtained from the Model. Also I created a xslt processor and fed it with the xsl file representing the View for the articles list. Finally I fired the method transformToXML() that tranforms the xml into HTML using the set of tranformation rules specified in the xslt file.

All the natively implemented classes at stake here belong to the DOM exstension (which comes out of the box with php5 and relies on the great libxml2 and libxslt). In the php website you can find loads of info about he functioning of these classes/methods. Instead, for a good and exhaustive guide on xslt, have a look at this tutorial (sorry but I really don't have time to talk about xslt here!).

As promised at the beginning of the article, the complete separation between php (programming language) and presentation (xslt) has been succesfully achieved. The front-end developer will be working ONLY on the xsl tranformations regardless of the logical layer managed via php. Also, during development phase, it might be useful to print a commented out version of the xml string containing the data from the db. This will give the front-end guy the opportunity to know what the data available (and therefore retrivable via xsl) are without bothering to open the php files where the xml is effectively created.

Let's now move on to the Model layer and see what it actually does. As well as for the xslt tranformation process, I won't go into many details and just show how the application should ideally work.

class defaultModel { public function __construct() { // it performs the connection to the db } public function getXMLData() { $query = "SELECT * FROM articles"; // it runs the query and loop into the obtained recordset // to create the xml-like string to return to the sub-controller $XSML = "<data>"; while ($row = mysql_fetch_array($result)) { $XML .= "<article id='" . $row[id] . "'>"; $XML .= "<title>" . $row[title] . "</title>"; $XML .= "<text>" . $row[text] . "</text>"; $XML .= "</article>"; } $XML .= "</data>"; return $XML; } }

The model layer is going to return the controller a xml-like string that is roughly going to look like this (I formatted it to make it more readable but all the return characters woulnd't be there):

<data> <article id='1'> <title>Title first article</title> <text>Content first article</text> </article> <article id='2'> <title>Title second article</title> <text>Content second article</text> </article> ... ... ... <article id='42'> <title>Title last article</title> <text>Content last article</text> </article> </data>

Now that the sub-controller can finally rely on a bunch of data in xml format, we are going to present the xsl file in which all the transformation process is specified. As I said this is not a xslt tutorial so no further explanations on the following code will be given. Here we go:

<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="4.0" encoding="iso-8859-1 " indent="yes"/> <xsl:template match="/"> <html> <head> <title>Articles List</title> </head> <h1>Article List</h1> <xsl:for-each select="data/article"> <a href="index.php?action=article&idArticle={@id}"> <xsl:value-of select="title"/> </a> <p> <xsl:value-of select="text"/> </p> </xsl:for-each> </html> </xsl:template> </xsl:stylesheet>

The code above should be fairly straightforward. One little thing that certainly deserves to be pointed out is the link tags wrapping the article titles in the list. The href attribute contains the parameter idArticle (which corresponds to the article's id in the db) and the name of action to be activated: article (which becomes articleAction after being processed by the frontController class). Clearly this dinamically-created links will all lead to a specific article specified by the id included in the URL. That it is to say that they will all trigger the other state of our application. Let's have a closer look ...

4. Showing a particular Article

Here's the sub-controller displaying the title and the content of the chosen article (the article specified by idArticle in the querystring).

class articleAction { public function __construct() { require_once("path/Models.php"); } public function exec($req) { $db = new articleModel(); $xmlString = $db->getXMLData($req['idArticle']); $xmlString = new DomDocument(); $xmlString->loadXML($XML); $xsl = new DomDocument(); $xsl->load("views/articleView.xsl"); $proc = new XSLTProcessor(); $proc->importStyleSheet($xsl); $HTML = $proc->transformToXML($xmlString); echo $HTML; echo "<!--\n\n"; echo $XML . "\n\n"; echo "-->"; } }

This time we pass the Model layer the parameter $req['idArticle'], which will be used in the query extracting the data about the article. Here is the Model:

class articleModel { public function __construct() { // it performs the connection to the db } public function getXMLData($idArticle) { $query = "SELECT * FROM articles WHERE id=" . $idArticle; // it runs the query and loop into the obtained recordset // to create the xml-like string to return to the sub-controller $XSML = "<article>"; while($row = mysql_fetch_array($result)){ $XML .= "<title>" . $row[title] . "</title>"; $XML .= "<content>" . $row[content] . "</content>"; } $XML .= "</article>"; return $XML; } }

Being the id passed unique in the db (ideally it's the primary key of the table containing the articles) we are going to obtain an xml-like string containing 1 single node, like this:

<article> <title>Title of the chosen article</title> <text>Content of the chosen article</text> </article>

Finally, the xsl that we need to tranform into HTML the xml bit we have just obtained, should roughly look like this:

<?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="html" version="4.0" encoding="iso-8859-1" indent="yes"/> <xsl:template match="/"> <html> <head> <title>Article</title> </head> <body> <h1>Article</h1> <h3> <xsl:value-of select="article/title"/> </h3> <p> <xsl:value-of select="article/text"/> </p> <a href="index.php">home</a> </body> </html> </xsl:template> </xsl:stylesheet>

Easy no? As you can see I have also added a link to the home page, namely the interface generated by the sub-controller defaultAction, so that there is a kind of ease of access throughout the whole application in case you wanted to implement and test it.

5. Conclusions

The articles has shown an oversimplyfied version of the MVC pattern. Clearly many additional parts should be add in the attempt to obtain a professional and flexible solution fitting all the possible requirements. But my purpose here was merely scholastic and my intent was simply to make you guyz touch with your own hands the foundation of a MVC pattern implementation. Hope you enjoyed the long article. Here you can also find a zip containing a copy of the code used in the article. Cheers

Enter Your Comment

  • html tags are not allowed but you can use [b] for bold, [code] for pre formatted code.
Joe> Tuesday 31st of March 2009 09:41:47 PM

Hey nice article. I haven't done much XSLT in my life but it looks like a good way of separating stuff. Thanks

G000085> Wednesday 15th of April 2009 02:19:00 PM

A really good article ... Thanks SOOoo much :)

Rafi B.> Friday 1st of May 2009 04:02:04 PM

MVC and XSLT in the same word... great!