Your controller has done all the heavy lifting and taken care of the "business logic", now it's time to get back to your client with a meaningful response. Where controllers are all about serving the client by doing and fetching, views are all about responding by presenting and rendering.

How you actually respond likely depends on: 1) what the HTTP client asks for "I want /person/1 in JSON", "Ok, the controller gave me the data for Person 1, here it is in JSON", and 2) the best way for you to get the job done: maybe it's using Smarty templates, maybe it's an automatic response, or maybe it's plain old PHP.

This brings us to the design goals of Recess' View system, which have been revamped in 0.20:

  • Flexible - The view system must simplify handling different response types: HTML, JSON, XML, PDF, etc.

  • Extensible - Users can create their own Views to accomodate preferences with template engine(s) or automating common responses.

  • Predictable - The logic for selecting a view should be straightforward. Assertive templates, covered later in this chapter, are also encouraged for improved predictability when authoring templates.

Before diving into specifics let's take a leading example of creating the view components for a hypothetical listing of blog posts. Suppose we have a Post model that has properties: title, author, and body. Our controller code will look like this:


We'll get into the details of the relevant annotations later, for now just take our word that the view class rendering the response will be LayoutsView, and it will be looking for the view template post/index.html.php found in the apps/[appname]/views/ sub-directory. The variable $postSet will be available to this template which represents a set of Post models.

Our first-pass, naive template implementation of post/index.html.php may look like this:


This works, but as our application grows in complexity we will want to remove redundant HTML to layouts shared by many views. Let's try creating a layout that this simple view can extend to remove common HTML.



As you can see, we've extracted the redundant HTML to a master layout. You'll notice that the master layout specifies its inputs. The child/parent templates do not share scope, the parent must define which inputs it requires and the type the variable should be. This improves predictability because you know exactly what variables a parent layout is expecting. If your child template fails to provide a variable required by the parent you will get a simple error message notifying you of the problem instead of an obscure 'variable not defined' message from somewhere deep in the parent template.

Unfortunately, our listing template has regressed. Storing the output of the list of posts in a string is painful. This is where Buffer'ing and Block save the day! Buffer is a class that uses PHP's output buffering to fill Blocks. The buffer fills a block. Let's take a look:


Now we don't have to worry about string concatenation, we let Buffer fill our $body Block. If we were to run this code we would get a type check error in the master layout: $body is expected to be a string, but now it is an instance of HtmlBlock which is a sub-class of Block. Why not just have Buffer fill strings? Shortly we'll see how Block's type-hierarchy enables really powerful features. The immediate benefit, though, is that it allows layouts to specify they are expecting a block of HTML, not just a string. Let's update our master layout.


Easy enough! Notice all we needed to change was the expected type on the input. We can echo a Block instance just like we can a string. Imagine we had some other places in our application where we'd really like to print out the list-item format of a Post. Enter: Parts to save the day! Parts are kind of like partial templates you may have used in other frameworks. Let's take a look at how we would define a part for post.


Notice the similarity with a layout: parts and layouts define their inputs. The term we coined for this style of a template is an Assertive Template. By being assertive about the inputs a template expects we can make working with these templates much more pleasant. Let's take a look at how we would use this part in post/index.html.php.


We can 'draw' a Part by passing the path to the part in the views directory, minus '.part.php', and the rest of the inputs in the order specified by the part. You pass a part inputs just like you call a function with arguments. Notice that the name of the variable passed to draw and the name of the input do not have to match, again, like functions. This is contrasted by most PHP partial libraries that would require calling the template with an array like array('aPost' => $post).

You'll also notice we're no longer buffering $body. But the code still works! What's going on? By default, if your child template does not specify a $body block, any output will automatically create a Block named $body that will be passed to its parent layout.

Let's say we wanted to make it possible to append another class to the post/li part. We can create an additional input that is optional by passing a third argument to Part::input which is the default value of an input.


Now, by default, the only class will be 'post', but others could be appended by passing an additional input to the part. Let's go back to our post/index.html.php template and make the additional class name of 'odd' be appended to every other item in our list. This way we can style every other post differently using CSS.


You can see by passing an additional input to post/li we are now appending the 'odd' class to odd posts. Suppose that throughout our project we use this even/odd classname technique in a number of places. Could we do any better and eliminate this redundancy? Yes, we can! We'll simply create a part for it.

Now, take a deep breath and hold on. Here comes the sexy stuff that makes our parts different from everyone else's partials. Earlier we alluded to there being some 'power' in passing around instances of Block instead of strings. You saw an example of how Buffer filled an HtmlBlock. There is a special Block for Parts, too, called PartBlock. Before we summon a PartBlock, though, let's first create the higher-order part that abstracts toggling between two blocks.


There are two interesting things going on here. First, notice that we're passing in two Block instances named $even and $odd. Second, notice that we're using the draw method of Block. Every Block has two methods: __tostring and draw. For an HtmlBlock created using Buffer, draw doesn't take any arguments (but won't complain if you give them). For a PartBlock, though, passing arguments to draw will apply those arguments where you left off in creating the PartBlock. Well, then, how do you create a PartBlock?


So, by using the block method instead of draw, the method returns a PartBlock with the parameters you've passed stored. You can think of this like currying in functional languages like Scala / OCaml. For the astute reader you'll notice we have a problem on our hands, though. In order to use our 'each-toggle' part $post must be the final argument passed to draw. We can solve this in one of two ways, first we could do the obvious and re-order the inputs so that our 'post/li' is passed a class string first and a Post second. That makes things ugly, though, because we really want class to be an optional parameter. Recess has a mechanism for assigning optional arguments to a PartBlock after it has been created. Let's take another look.


This style of assignment is inspired by the jQuery library and uses method chaining to make it easier to specify multiple optional arguments. Notice that the 'class' method corresponds to the $class input of the 'post/li' part. Now we're finally equipt to use our higher-order 'each-toggle' template! Let's take a look:


Voila! Simple and beautiful. If we wanted to be really pedantic we could even make a part for a list of posts. In this case it's a little excessive, but let's do it just to demonstrate how parts can be composed. Let's start with the code we'd like to end up with in post/index.html.php template and design the part from it.



This wraps up our leading tutorial of the new view system in Recess 0.2! Blocks, Parts, and Layouts are the keywords. Blocks are chunks of HTML that haven't been rendered yet and can be static with HtmlBlock or wrap around parts with PartBlock. Layouts are advanced includes that safely transfer variables from a child template to a parent layout. This is possible because parent layouts specify their inputs. Parts, kind of like partials, also specify their inputs. Parts and Layouts are considered to be Assertive Templates for this reason. Parts can become blocks, kind of like functions can become lambdas, to enable powerful higher-order part templating.