{some_text}
{some_more_text}
Have no understanding of the document they will become, what they represent and are simply there for PHP to replace them with something else.
If you agree with this loose description of a View, you'll also agree that most of the template engines fail to create the desired division between View and Model, the knowledge of what the template tags will become having to be stored within the Model.
Some questions to ask yourself when implementing Views: "How easy is it to make global changes to all views?", "How long does it take to implement new views?", "Can presentation language delivered by the View be easily interchanged with another (e.g. deliver a SOAP document instead of an HTML document from the same View).
======The Model======
The Model represents application logic (often called the business layer in enterprise applications).
Generally speaking, it's the job of the Model to transform raw data into data which contains some sort of meaning, which is then delivered to the View for display. Frequently the Model will encapsulate database queries, perhaps taking advantage of an abstract database class (a data access layer) to actually perform the queries.
For example, say you wanted to calculate the yearly rainfall in the United Kingdom (just to convince yourself there's better places for a holiday), the Model would receive a set of daily rainfall figures for ten years then perform an average and deliver it to the View.
======The Controller======
The controller is basically the first point of call for any incoming HTTP requests in a web application. It examines what it received in the request, such as a collection of GET variables, as responds appropiately. You can hardly even begin coding PHP without writing your first controller of some sort. The most common use is something like a switch() statement in your index.php such as;
display();
?>
That's using a mix of procedural and object oriented code but for a small website, is frequently a perfectly valid choice. The above code could do better though.
The Controller is essentially the component which triggers the binding of data from the Model to elements in the View.
======An Example======
Here's a simple example of the MVC pattern in action.
First we need a data access layer, which is generic class;
db=mysql_pconnect($host,$user,$pass);
mysql_select_db($db,$this->db);
}
//! An accessor
/**
* Fetches a query resources and stores it in a local member
* @param $sql string the database query to run
* @return void
*/
function fetch($sql) {
$this->query=mysql_unbuffered_query($sql,$this->db); // Perform query here
}
//! An accessor
/**
* Returns an associative array of a query row
* @return mixed
*/
function getRow () {
if ( $row=mysql_fetch_array($this->query,MYSQL_ASSOC) )
return $row;
else
return false;
}
}
?>
On top of this be place the Model;
dao=& $dao;
}
//! A manipulator
/**
* Tells the $dboject to store this query as a resource
* @param $start the row to start from
* @param $rows the number of rows to fetch
* @return void
*/
function listProducts($start=1,$rows=50) {
$this->dao->fetch("SELECT * FROM products LIMIT ".$start.", ".$rows);
}
//! A manipulator
/**
* Tells the $dboject to store this query as a resource
* @param $id a primary key for a row
* @return void
*/
function listProduct($id) {
$this->dao->fetch("SELECT * FROM products WHERE PRODUCTID='".$id."'");
}
//! A manipulator
/**
* Fetches a product as an associative array from the $dbobject
* @return mixed
*/
function getProduct() {
if ( $product=$this->dao->getRow() )
return $product;
else
return false;
}
}
?>
One thing to note is between the Model and the data access class, they never exchange more than a single row as an array - there's no passing of multiple rows, which can serious slow an application down. The same applies to the class which uses the Model - it need only ever hold one row in memory - the rest is down to a stored query resource - in other words we leave to MySQL to hold the result for us.
Next the View - I've left out the HTML to save space but you'll find it in the complete code for this article.
model=& $model;
}
//! A manipulator
/**
* Builds the top of an HTML page
* @return void
*/
function header () {
}
//! A manipulator
/**
* Builds the bottom of an HTML page
* @return void
*/
function footer () {
}
//! A manipulator
/**
* Displays a single product
* @return void
*/
function productItem($id=1) {
$this->model->listProduct($id);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
//! A manipulator
/**
* Builds a product table
* @return void
*/
function productTable($rownum=1) {
$rowsperpage='20';
$this->model->listProducts($rownum,$rowsperpage);
while ( $product=$this->model->getProduct() ) {
// Bind data to HTML
}
}
//! An accessor
/**
* Returns the rendered HTML
* @return string
*/
function display () {
return $this->output;
}
}
?>
And finally the Controller, which we'll have implement the View as a child;
header();
switch ( $getvars['view'] ) {
case "product":
$this->productItem($getvars['id']);
break;
default:
if ( empty ($getvars['rownum']) ) {
$this->productTable();
} else {
$this->productTable($getvars['rownum']);
}
break;
}
$this->footer();
}
}
?>
{{design:archive:mvc.gif?200x118}}
Note that this is not the only way to relate the classes in an MCV pattern - you might choose to have the controller implement the Model while aggregating the View, for example. This is just one approach which demonstrates the pattern.
Our index.php looks like this;
display();
?>
Nice and simple.
We could have been more cunning with the controller it's worth noting. With PHP you can pull stunts like this;
$this->{$_GET['method']}($_GET['param']);
What that approach suggests is you need to define your applications URL namespace doing so that it conforms to a standard such as:
"index.php?class=ProductView&method=productItem&id=4"
Using that we could do the following in our controller;
$view=new $_GET['class'];
$view->{$_GET['method']($_GET['id']);
In some ways, building the controller is the hardest part, when trying to balance rapid development with scalability. A good place to get inspiration is [[http://jakarta.apache.org/struts/userGuide/building_controller.html|Java Struts]] by the Apache group, where your controller is essentially defined by XML documents.