awhitebox


Partial Templates in Lithium

Update: I’ve put the helper explained below in a lithium plugin so that it can be easily reused instead of copying the helper across all of your webapps. Installation is super easy and is explained in the plugin’s README.

When building web applications with a MVC framework, we are bound to end up with views that share common form field. For example, both ‘New Post’ and ‘Edit Post’ will both have ‘Post title’, ‘Post content’ and so forth.

Most frameworks already have solutions for that. I know that Rails uses partial templates – most commonly known as partials. Put simply, partials are templates that can be rendered and re-rendered by views.

Lithium already has something very similar, dubbed “Elements”. So it’s already exceptionally trivial to render a template from within a lithium view.

Consider the following example view, views/posts/add.html.php:

<?=$this->form->create($post)?>
  <?=$this->form->field('title', array('type' => 'text'))?>
  <?=$this->form->field('content', array('type' => 'textarea'))?>
  <?=$this->form->submit('Add Post')?>
<?=$this->form->end()?>

We would probably have at least one other view, views/posts/edit.html.php with the content of which would look very similar to the above.

Say, as an example, both views share a common chunk, that is the two lines where field is called. We can then, move those two lines to a separate file views/elements/fields.html.php, and render it directly from within the views:

<?=$this->form->create($post)?>
  <?=$this->view()->render(array('element' => 'fields'))?>
  <?=$this->form->submit('Add Post')?>
<?=$this->form->end()?>

Works like a charm, but slightly ugly for my taste! And it seemed to me that there was a cleaner way to render these templates, and that is to use a helper.

Creating a helper in Lithium is quite easy. We simply extend the \lithium\template\Helper class:

<?php

// Partial.php

namespace app\extensions\helper;

class Partial extends \lithium\template\Helper {
  public function __call($method, $args) {
    $params = empty($args)? array() : $args[0];
    return $this->_context->view()->render(array('element'=> "{$method}_partial"), $params);
  }
}
?>

Placing the class file above in our app’s extensions\helper should do the trick. Now, we simply call the partial helper from the view to render the partial:

<?=$this->form->create($post)?>
  <?=$this->partial->fields()?>
  <?=$this->form->submit('Add Post')?>
<?=$this->form->end()?>

Good! You can also pass in arbitrary variables to the partial templates as an array (e.g. using compact()):

<?=$this->partial->fields(compact('foo', 'bar'))?>

The renderer will extract that array to make the variables $foo and $bar available for the fields.html.php template to use.

More on templates and helpers in Lithium can be found here.

You can respond to this article by replying on twitter or sending me an email.