web development articles and portfolio

Custom PHP MVC Tutorial: Part 5, Views

Posted on 14-10-2011

When I first started to code websites in PHP, my understanding of separating PHP code from HTML consisted of complex string concatenation and a scary amount of character escaping. When I first started using MVC frameworks a little while back, it was like chocolate mud cake started to fall (safely) from the sky - my HTML finally looked like HTML, and not HTML murdered by server side coding syntax.

This, in essence, is the point of MVC. By putting framework level code in one spot (controllers and supporting infrastructure) and business logic, data access/manipulation code in another spot (models), we are able to put the presentation code (views) in yet another spot, ready to accept data already specifically prepared. This means views can have minimal code outside of HTML, XML, or whatever else you can use for browsers these days.

Carrying on from the earlier parts in this series of articles, the following view is for the Home controller's Index action - which we are sending an array of strings, as defined in Part 4:

<ul>
<?php foreach($viewmodel as $item) { ?>
<li><?php echo $item; ?></li>
<?php } ?>
</ul>

In this view, we're creating a HTML unordered list based on the array the controller retrieved from the model and sent to the view. $viewmodel is how we access the data the controller sends to the view, because this is how the BaseController's ReturnView method defines it.

There is not a whole lot of HTML in this view, because if you can recall, in the Index method of our Home controller we supplied "true" to the ReturnView method, which means "yes, I want the full template for this action, thanks". Speaking of the ReturnView method, here it is again for a refresher:

protected function ReturnView($viewmodel, $fullview) {
$viewloc = 'views/' . get_class($this) . '/' . $this->action . '.php';
if ($fullview) {
require('views/maintemplate.php');
} else {
require($viewloc);
}
}

When the Home controller calls the ReturnView method from its Index method, it determines the location of the view based on the controller and action name and stores that location in the variable $viewloc, and then, depending on whether $fullview is true or not, either shows the view directly, or shows the main template, both via a PHP require.

For the main template to show the view's content, you simply need to put the following (inside PHP tags) where you want the content of the view to display:

require($viewloc);

Because the entire handling of the view is done within the context of BaseController::ReturnView(), variables like $viewmodel, $viewloc and $fullview are accessible to our main template and view files, so you can easily add page titles to the main template, metadata, etc by making sure to include that information as part of the model's return data.

If you want to add dynamic data to the main template, for example a tag cloud for a blog application, then matters get a little bit more complicated. One way to do this would be to simply remember to retrieve the data in every model's method you're returning for consumption by the view (and hence main template), but this is not very efficient and would basically equate to copy and pasting code across all your model methods (another OO no-no).

Probably the best way to achieve this is what was mentioned in Part 4 - a BaseModel class that your models extend from. This would allow you to define a property that you always use when returning data from your models. In your BaseModel class, you could populate this property in the construct method with the data you need for the main template so, when the controller method creates the model instance, this data is always present. Then in your model methods that are used to supply data to ReturnView, you would add to, not replace, the value of this property. This BaseModel property could be an instance of a class you define, perhaps a class which dynamically adds properties to itself, like so:

class ViewModel {
public function Add($name,$value) {
$this->$name = $value;
}
}

If BaseModel::ViewModel was the property we create for this purpose, and it was an instance of ViewModel as defined above, we could do a $this->ViewModel->Add("Property","Value") in the BaseModel construct method, and then do the same thing again (but with something other than "Key") in a method of a model class that extends from BaseModel, and then both values would be accessible to the main template and views as $ViewModel->Property and Property2, or whatever we call the second one. Of course, this isn't limited to two occasions - you can do this as many times as needed.

This concludes Part5 regarding the View and, in fact, concludes all the technical discussion needed to get this framework operating. If all the code supplied so far was put in the right files in the rights spots, navigating to /home/index should display a HTML list based on the array supplied to the view. In Part 6, I'll cover where you might go from here with this PHP MVC framework.

Part 1 - Introduction
Part 2 - URL mapping and index.php
Part 3 - Controllers
Part 4 - Models
Part 5 - Views
Part 6 - Where to now

Social

Tags

Comments

comments powered by Disqus
perfmonUI