This post explains how to integrate the Smarty templating engine with the CodeIgniter MVC framework.

CodeIgniter ships with its own templating system, which is nice and simple to use, is fast and works well apart from one thing, which is a deal-breaker: It doesn’t support partial page caching. Why is that bad? Well, to make your website as fast as possible you don’t want to read the database and assemble the HTML of a page every time someone requests it, you want to assemble it once and the store the assembled file in a cache for quick retrieval and display from then on. This task would be easy if you didn’t show user-specific information, you could just cache a page once and deliver that to every user until the cache entry expires and you generate a new one. Most websites, however, do show user-specific information, an e-commerce site, for example, would probably show your username and the number of items in your basket. So you can’t cache the whole page but you do want to cache as much as possible: on an e-commerce site you want to cache the list of products being shown so you don’t have to get them from the database again, the marketing text pulled-in from a CMS and other time-consuming stuff.

Out of the box CodeIgniter won’t let you cache the e-commerce products but still show a user’s name and cart total because it doesn’t do partial page caching, but Smarty does and that’s why I always use Smarty in my CI projects.

Fortunately, integrating Smarty is a simple case of creating a new CodeIgniter Library to wrap Smarty and calling it from your controller. Here’s how:

  1. Download the Smarty library Zip file and copy the Smarty directory from the Zip into your Code Igniter project’s /application/third_party folder. You should now have a directory along the lines of /application/third_party/Smarty-3.1.8/ in your project.
  2. Create a new PHP file in the /application/libraries/ folder called Smartyci.php.
  3. Paste the following into Smartyci.php:
<?php

if ( ! defined('BASEPATH') )
    exit( 'No direct script access allowed' );

require_once( 'application/third_party/Smarty-3.1.8/libs/Smarty.class.php' );
class Smartyci extends Smarty
{
    public function __construct()
    {
        parent::__construct();

        $config =& get_config();

        $this->caching = 1;
        $this->setTemplateDir( $config['application_dir'] . 'views' );
        $this->setCompileDir( $config['application_dir'] . 'third_party/Smarty-3.1.8/templates_c' );
        $this->setConfigDir( $config['application_dir'] . 'third_party/Smarty-3.1.8/configs' );
        $this->setCacheDir( $config['application_dir'] . 'cache' );
    }

    //if specified template is cached then display template and exit, otherwise, do nothing.
    public function useCached( $tpl, $cacheId = null )
    {
        if ( $this->isCached( $tpl, $cacheId ) )
        {
            $this->display( $tpl, $cacheId );
            exit();
        }
    }
}
  1. Create Smarty .tpl files in your /application/views/ directory instead of standard CodeIgniter views. For example, for the home page you would create a home.tpl file in /views instead of home.php.
  2. Finally, in your Controller classes you need to load your new Smartyci library and tell it to render a .tpl file using some data. The data will probably have been loaded by your Controller from a Model. Here’s an example for a home page:
class Home extends CI_Controller
{
    public function index()
    {
        $this->load->library( 'smartyci' );
        $this->smartyci->useCached( 'home.tpl' );

        $this->smartyci->display( 'home.tpl' );
    }
}

Don’t forget to amend the Smarty version number if you download a newer version.

The constructor of the Smartyci class turns on caching with $this->caching = 1; you can set different caching options, refer to the Smarty caching page. The rest of the constructor sets directories that Smarty will use – the code uses the default CodeIgniter location for views and cached files. The only function in the Smartyci class is useCached(), if you call this from your Controller it will check to see if the page being created by the Controller already exists in the cache and if it does it will display from cache and exit – you can use this to quickly show pages from cache if you don’t need to insert any user-specific data.

If you have a Controller that needs to set user-specific data, in our example above the cart total items and user’s name, then you need to alter the Controller’s flow a little bit, here’s another example, this time for a product listing page where we want to read the products and cache them but we do not want to cache the user’s name or their cart item count:

class Products extends CI_Controller
{
    public function index()
    {
        $this->load->library( 'smartyci' );

        if ( $this->smartyci->isCached( "products.tpl" ) == false )
        {
            $this->smartyci->assign( 'products', getProducts() );
        }

        $this->smartyci->assign( 'cartitems', getCartTotal() );
        $this->smartyci->assign( 'username', getUsername() );
        $this->smartyci->display( 'products.tpl' );
    }
}

This time we can’t just blindly call useCached() because we want to add in our user-specific data. Note the call to the getProducts() function is inside the checked to see if the page is already cached, if it is cached then we don’t need to hit the database to get the product info. The getCartTotal() and getUsername() calls are outside of the cache check because they must always be called; ideally these two would only be checking session variables rather than hitting the database.

The actual integration of Smarty and CodeIgniter is very easy, you need only create the library in Step 3 and call it. What I haven’t described in detail here is the different options for caching in Smarty – this post is about integrating Smarty with CodeIgniter and not a detailed how-to on Smarty caching. To find out how to make a section of a .tpl template dynamic (so that you always show the current user’s name and cart total) read this. To find out how to control cache lifetimes and how to flush a cache entry read this. To find out how to store multiples cache entries for one page read this – this is useful if you have, for example, a page that shows different category contents based on a URL parameter but you always show the page with category.tpl: you don’t want to cache only one version of category.tpl, you want to cache one version for each category as specified by the URL parameter.