A Guide to Using Template

A new version of the Template Library is available! Please upgrade.

Looking for documentation covering how to install Template? Head over to Getting Started. Or, learn more about the project in the Introduction.

User Guide Topics

Configuration

Template uses its own configuration file template.php. This file must be placed inside the config folder, alongside config.php, database.php, autoload.php, et. al.

Open config/template.php in a text editor and you'll notice that, much like CodeIgniter's config files, all configurations for Template are stored in a singly array, except ours is stored in the $template variable. Also, much like config/database.php, Template lets you define templates in "groups," which allows you to use and switch between multiple templates in your application.

Setting the Default Template

Template requires that you have at least one active template group set with a master template defined.

$template['active_group'] = 'default';
$template['default']['template'] = 'template.php';

For $template['default']['template'], indicate the filename of your master template in the views folder. Typically this file will contain a full HTML or XML skeleton that outputs your pre-defined regions. Details of this file will be outlined below.

Note: Template will error if this file cannot be found in your views folder. This can also be a relative path if you desire to nest your master template in folders inside views.

Defining Regions

What are regions? Regions are places within the template where your content may land. They are defined in the $template['regions'] array following an easy-to-understand prototype. You may include default markup, wrappers and attributes here (not recommended), or you can simply define region variables that you intend to use.

A simple regions array:

$template['default']['regions'] = array(
  'header',
  'content',
  'footer',
);

exposes $header, $content, and $footer regions to be written to by your application and placed in your master template.

Note: Region keys must gracefully translate into variables (no spaces or dashes, etc).

Regions can be extended to include default contents and wrapping markup if desired. To do this, turn your region keys into multidimensional arrays with the following possible indeces:

Index Instructions
content Must be an array! Use to set default region content
name A string to identify the region, beyond how it is defined by the key.
wrapper An HTML element to wrap the region contents in. (We recommend doing this in your template file.)
attributes Multidimensional array defining HTML attributes of the wrapper. (We recommend doing this in your template file.)

For example:

$template['default']['regions'] = array(
  'header' => array(
    'content' => array('<h1>Welcome</h1>','<p>Hello World</p>'),
    'name' => 'Page Header',
    'wrapper' => '<div>',
    'attributes' => array('id' => 'header', 'class' => 'clearfix')
  )
);

Would result in <div id="header" class="clearfix"><h1>Welcome</h1><p>Hello World</p></div> when finally rendered by Template.

Creating the Master Template

Let's start using Template by creating a master template. We've got a basic design that's going to fulfill 95% of page views for our imaginary site:

A simple two-column design with a header and a footer Fig. 1 A simple two-column design with a header and a footer

Based on this design, we can define a few pieces that work well as regions—parts of the design that might change per page. So, let's configure config/template.php with the following regions:

$template['default']['regions'] = array(
  'header',
  'title',
  'content',
  'sidebar',
  'footer',
);

It looks like our header and footer regions will have the same content on just about every page. Keeping them as regions will make our template flexible, but we can also define default content for these regions, which we can either append or overwrite from our code. We'll add these lines of code to the bottom of config/template.php:

$template['default']['regions']['header'] = array('content' => array('<h1>CI Rocks!</h1>'));
$template['default']['regions']['footer'] = array('content' => array('<p id="copyright">© Our Company Inc.</p>'));

Finally! We're all set. Let's code our master template file at views/template.php, outputting our regions in the appropriate places: (For the sake of brevity, this example will be poorly structured HTML and make use of PHP short tags.)

That's all! For now at least. Continue on to see how to make use of this template and regions throughout your application's Controllers.

Writing to Regions

With our regions defined and the basic structure of our template in place, we can start writing to our template from our controller.

$this->template->load($template_file)

This is the method that outputs our rendered template to the browser or other client. This method should be the last thing called from any public Controller methods that make use of the Template Libary.

Let's start with a basic controller called 'page' that, by default, loads our template as is by calling $this->template->load() without passing a $template_file (so that it uses the default template group's master template, which we defined in config/template.php):

Now, when we load this page in the browser, we see:

The template has an empty content and sidebar because we haven't written anything to these regions. Fig. 2 Our template is loaded with only default content appearing.

As you can see, the content, title and sidebar regions are showing empty because we've yet to write content to those regions, and we didn't configure any default content in config/template.php. Additionally, our validator is probably screaming at us because we've got an empty <h2> tag where $title should be. Let's take care of that.

$this->template->write($region, $content, $overwrite = FALSE)

Template's write() method is the most common way of writing content to a region. At a minimum, this method must be passed $region, a string defining to which region we wish to write, and $content, a string containing the content we wish to write. The default behavior of the write() method is to append $content to what has already been written to the given $region, but we can alter this behavior and overwrite all existing region contents by passing TRUE as a third argument.

$this->template->write('content', 'You one ');
$this->template->write('content', 'bad mother...');
// $content region = "You one bad mother..."

$this->template->write('content', "Shut'yo mouth!", TRUE);
// $content region = "Shut'yo mouth!"

$this->template->write_view($region, $view_file, $view_data, $overwrite = FALSE)

Using the write() method, we could load the result of a View into a variable and then write it to a region in our template, but Template provides the write_view() method to expedite the process and save you from writing at least one extra line of code per use!

Like write(), we define the region we wish to write to in the first argument of write_view(). For the second and third arguments, we pass a view file (with or without the ".php" extension) and optionally pass a data array to our view, respectively, just as is typically done with CI's $this->load->view() method. Again, if we wish to overwrite any existing content in the region, we can pass TRUE as a fourth argument.

$data = array('name' => 'John Smith', 'birthdate' => '11/15/1950');
$this->template->write_view('content', 'user/profile', $data, TRUE);
 
/* Template loads the views/user/profile.php view with the $data array passed in
and writes the result to the $content region, overwriting any previous content in the region */

Let's use these two methods to fill out our template:

Now, when we load up our Page controller in the browser, we see our completed Web page:

A simple two-column design with a header and a footer Fig. 3 Avoiding messy code and calling views from within views, we've filled out our template with just a few calls to Template methods in our Page controller.

Cascading Views

A core principle of the Template library is flexibility, so the write_view() method lets you suggest other View files to load if the defualt View file you passed in the first argument doesn't exist. To suggest other View files for Template to use, pass them discretely, starting with the 5th argument:

$data['posts'] = $this->blog->get_recent(5);
$this->template->write_view('content', 'blog/front', $data, FALSE, 'blog/posts');

If this was a blog application, using this method lets us create a View file at views/blog/front.php to format blog posts distinctly when they appear on the front page, or opt-out and let our standard views/blog/posts.php handle the output. We could suggest more fallbacks if needed in the 6th, 7th, 8th arguments, and so on.

$this->template->parse_view($region, $view_file, $view_data, $overwrite = FALSE)

If you would rather use CodeIgniter's Template Parser class to parse a View, use the parse_view() method. parse_view() works identically to write_view(), so you can suggest other Views to parse just as well.

$data = array(
            'blog_title' => 'My Blog Title',
            'blog_heading' => 'My Blog Heading'
);
$this->template->parse_view('content', 'blog_template', $data);

What happens if I write to a region that I hadn't previously defined?

Template will show an error if you attempt to write to a region that was not previously defined in the config file or otherwise. See how to manipulate templates and template regions in the following section, "Dynamically Manipulating Template."

Dynamically Manipulating Template

The whole idea of Template is to improve the interface between your application's business logic and presentational markup by providing a very flexible wrapper to CI's Views implementation. Consider an application that required two or more markedly different templates for different pages or sections (like a blog with a main HTML template and RSS feed template). Or, consider if a plugin architecture was to allow for making components available to all your pages (like a User plugin that provides a login form). Rather than limiting it to using the regions defined in your configuration, a plugin should be able to dynamically provide its own regions for writing. These methods allow for these and other development scenarios.

$this->template->set_template($group)

The set_template() method is how you switch between different template groups defined in your config/template.php file. Template will throw an error if you attempt to set a template group not previously defined or dynamically added.

$this->template->set_template('rss');

// Template will now use the master template and regions from the $template['rss'] group

Tip: Use this method in Controller constructors where the entire Controller uses a separate template.

$this->template->add_template($group, $template, $switch)

Not all templates must be defined in config/template.php. The add_template() method allows templates to be dynamically added, and you can pass TRUE as a third parameter to switch to the added template.

$rss['template'] = 'rss.php';
$rss['regions'] = array('name', 'items');
$this->template->add_template('rss', $rss, TRUE);

// Template will now use the master template and regions from the supplied $rss template group configuration

$this->template->add_region($name, $settings = array())

The add_region() method allows one to dynamically add regions for writing. At a minimum, a $name must be supplied to identify the region. Optionally, a $settings array can be passed in to provide default content, wrappers and attributes.

$this->template->add_region('user_login');
$this->template->write_view('user_login', 'user/login_block');

Template will throw an error if $name has already been defined.

Additional Utilities

CSS defines the style of your HTML template and JavaScript defines its behavior, so I've included two methods to easily include these important assets on-demand.

$this->template->add_js($script, $type = 'import', $defer = FALSE)

  1. $script: Depending on the value of the $type argument, either a path to the JavaScript file (including file extension) relative to $config['base_path'] or inline JavaScript code.
  2. $type: Either 'import' or 'embed' Use 'import' to include an external JavaScript file or 'embed' to wrap JavaScript code in <script> tags.
  3. $defer: Set to TRUE to include defer="defer" declaration on script tag.
$this->template->add_js('js/jquery.js');
$this->template->add_js('alert("Hello!");', 'embed');

Echo $_scripts in your template (preferably in the <head> section) to utilize JavaScript added via this method.

$this->template->add_css($style, $type = 'link', $media = FALSE)

  1. $style: Depending on the value of the $type argument, either a path to the CSS file (including file extension) relative to $config['base_path'] or inline CSS code.
  2. $type: Either 'link', 'import' or 'embed' Use 'link' to include an external CSS file, 'import' to include an external CSS file via the @import command, or 'embed' to wrap inline CSS code in <style> tags.
  3. $media: Set media declaration, like 'all', 'screen', 'print', 'handheld', etc.
$this->template->add_css('css/main.css');
$this->template->add_css('#logo {display: block}', 'embed', 'print');

Echo $_styles in your template (preferably in the <head> section) to utilize CSS added via this method.

Note: The add_css() and add_js() methods do not verify that the requested assets exist on the server's filesystem. Remember to pass file paths relative to the path defined for $config['base_path']. Both methods will return FALSE if an invalid $type argument is supplied.

More utilities, like setting META tags, language declarations, and other goodies typically found in an HTML document's HEAD will be considered for future releases. You can, of course, define regions to house these types of things in the meantime.