PHP – Smarty block caching

It might sound like a trivial task to cache Smarty templates, but when your website starts growing you should consider some more advanced strategies of caching your content using Smarty.


Normally you would just cache the entire page and your code would look like this:

<?php
mysql_connect(...);
$smarty = new Smarty();
$smarty->caching = 1;
$smarty->cache_lifetime = 2 * 60 * 60; // 2h cache
/* smarty configuration goes here */

if (!$smarty->is_cached($my_templatename,$my_key)
{
  /* fetch and assign meta keywords */
  /* fetch and assign navigation */
  /* fetch and assign contents */
}

$smarty->display($my_template,$my_key);

This is basically a good thing to do, but there’s still more you can do. Most website are split into at least 3 different template blocks: header / content / footer. The header usually contains meta informations, JavaScript & CSS files and the page navigation. Let’s assume the page navigation is stored in a database and you query the first level of the navigation as well as the 2nd and 3rd level of subpages for a fancy JavaScript layer menu.
So, the header is always the same on every single page of your website. Why should you bother the DB each time Smarty caches a new page?

Split your code into blocks.

Let’s assume your generic page.tpl file looks like this:

{include file="header.tpl"}

{foreach from=$news item="item"}
  <div>
      <h2>{$item.headline}</h2>
      <p>{$item.text}</p>
    </div>
{/foreach}
{include file="footer.tpl"}

Instead of including the template file for the header on each page, which requires fetching the navigation on every single page, put it into a Smarty Insert Plugin and cache is seperately.

<?php
mysql_connect(...);
$smarty = new Smarty();
$smarty->caching = 1;
$smarty->cache_lifetime = 2 * 60 * 60; // 2h cache
/* smarty configuration goes here */

function insert_header($params)
{
  global $smarty;
  $tmp_cache = $smarty->caching; //store the current caching value
  $tmp_lifetime = $smarty->cache_lifetime; // store the current cache liftime value
 
  $smarty->caching = 1; //force caching
  $smarty->cache_lifetime = 24*60*60; //24hours of lifetime

    if (!$smarty->is_cached('header.tpl'))
    {
      /* fetch and assign meta keywords */
      /* fetch and assign navigation */
    }
    $tmp_html = $smarty->fetch('header.tpl');
    $smarty->caching = $tmp_cache; // restore caching value
    $smarty->cache_lifetime = $tmp_lifetime; // restore lifetime value
   
    return $tmp_html; // return header

}

if (!$smarty->is_cached($my_templatename,$my_key)
{
  /* fetch and assign contents */
}

$smarty->display($my_template,$my_key);

Now you only need to modify for page.tpl file to make use of the new insert function:

{insert name="header"}

{foreach from=$news item="item"}
  <div>
      <h2>{$item.headline}</h2>
      <p>{$item.text}</p>
    </div>
{/foreach}
{include file="footer.tpl"}

That’s it! Now your page will only fetch the navigation from the database on the first page load and store the entire template for 24hours.

This is just the very basic idea of splitting pages into blocks and I hope you got the point. Of course, you can apply this approach on many parts of your website.


Leave a Reply