Caching of included sub templates (Smarty version 2.6.9)
[email protected] (Nick Payne) Fri, 04 May 2007 16:15:15 +0100
| Newsgroups | php.smarty.dev |
|---|---|
| Message-ID | <[email protected]> |
--------------090308010305020907040808
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Hey list,
Due to the way we use smarty in our PHP framework we needed a way to
only cache certain templates included within other top level templates.
For example, home.tpl includes within it menu-top.tpl - a dynamically
generated menu which requires a large number of MySQL queries to
generate the navigational menu for a website. Whilst we don't want most
of the content on the home page to ever be cached, it's of use to cache
the menu for short periods of time (as low as 60 seconds) as on high
traffic sites it greatly reduces the number of database queries needed -
we can live with a 1 or 2 minute stale menu for the amount of queries it
saves us.
We haven't used smarty's caching until now and couldn't see a way of
achieving this, and after a bit of experimenting (and to be honest,
trial and error) came up with the following solution. The only function
which has been changed is _smarty_include($params) in Smarty.class.php.
Two things:
1) It might be a bit of a hack, but it seems to work - no doubt there's
a better way of doing it.
2) We might be re-inventing the wheel & missing out on existing smarty
caching abilities that can do exactly this for us already. If so, please
enlighten us :)
Example usage:
--home.tpl
<div id="menu">
{include file="menu-top.tpl" __cache__=60} {* cache the menu for
1 minute *}
</div>
<div id="pagecontent">
... get dynamic page content (never want cached)...
</div>
Code:
--Smarty.class.php
function _smarty_include($params)
{
static $_cache_info = array(); // needed for cache stack
if ($this->debugging) {
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$debug_start_time = smarty_core_get_microtime($_params, $this);
$this->_smarty_debug_info[] = array('type' => 'template',
'filename' =>
$params['smarty_include_tpl_file'],
'depth' =>
++$this->_inclusion_depth);
$included_tpls_idx = count($this->_smarty_debug_info) - 1;
}
// check for special '__cache__' variable
$cache = $params['smarty_include_vars']['__cache__'];
unset($params['smarty_include_vars']['__cache__']);
//If caching check for cached version, and return if found
if($cache != "") {
/* save cache lifetime */
$_cache_lifetime = $this->cache_lifetime;
/* set to $cache */
$this->cache_lifetime = $cache;
// the following section mimics normal smarty caching behaviour...
$resource_name = $params['smarty_include_tpl_file'];
// save old cache_info, initialize cache_info
array_push($_cache_info, $this->_cache_info);
$this->_cache_info = array();
$_params = array(
'tpl_file' => $resource_name,
'cache_id' => '',
'compile_id' => '',
'results' => "",
);
require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
if (smarty_core_read_cache_file($_params, $this)) {
$_smarty_results = $_params['results'];
if (!empty($this->_cache_info['insert_tags'])) {
$_params = array('plugins' =>
$this->_cache_info['insert_tags']);
require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
smarty_core_load_plugins($_params, $this);
$_params = array('results' => $_smarty_results);
require_once(SMARTY_CORE_DIR .
'core.process_cached_inserts.php');
$_smarty_results =
smarty_core_process_cached_inserts($_params, $this);
}
if (!empty($this->_cache_info['cache_serials'])) {
$_params = array('results' => $_smarty_results);
require_once(SMARTY_CORE_DIR .
'core.process_compiled_include.php');
$_smarty_results =
smarty_core_process_compiled_include($_params, $this);
}
echo $_smarty_results;
return true;
}
//ASSERT: NO CACHE AVAILABLE
$this->_cache_info['template'][$resource_name] = true;
}
// normal behaviour - either no __cache__ variable passed,
// or no cached template available
$this->_tpl_vars = array_merge($this->_tpl_vars,
$params['smarty_include_vars']);
// config vars are treated as local, so push a copy of the
// current ones onto the front of the stack
array_unshift($this->_config, $this->_config[0]);
$_smarty_compile_path =
$this->_get_compile_path($params['smarty_include_tpl_file']);
if ($this->_is_compiled($params['smarty_include_tpl_file'],
$_smarty_compile_path)
||
$this->_compile_resource($params['smarty_include_tpl_file'],
$_smarty_compile_path))
{
// if caching, we need to isolate included tpl output and
then put that in cache
if($cache != "") {
/* save output buffer for later */
$ob_pre = ob_get_contents();
ob_end_clean();
ob_start();
}
include($_smarty_compile_path);
if($cache != "") {
/* save output buffer (included tpl) into cache */
$_params["results"] = ob_get_contents();
ob_end_clean();
ob_start();
/* restore original output buffer */
echo $ob_pre;
}
}
if($cache != "") {
/* write cache file */
require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');
smarty_core_write_cache_file($_params, $this);
require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
$_smarty_results =
smarty_core_process_cached_inserts($_params, $this);
// restore initial cache_info
$this->_cache_info = array_pop($_cache_info);
$this->cache_lifetime = $_cache_lifetime;
//actually output data this run
echo $_smarty_results;
return true;
}
// pop the local vars off the front of the stack
array_shift($this->_config);
$this->_inclusion_depth--;
if ($this->debugging) {
// capture time for debugging info
$_params = array();
require_once(SMARTY_CORE_DIR . 'core.get_microtime.php');
$this->_smarty_debug_info[$included_tpls_idx]['exec_time'] =
smarty_core_get_microtime($_params, $this) - $debug_start_time;
}
if ($this->caching) {
$this->_cache_info['template'][$params['smarty_include_tpl_file']] = true;
}
}
Apologies for the length of the code snippet - needed the whole function
to illustrate the changes made (a diff of the original and modified file
is attached).
Any suggestions or comments would be greatly appreciated.
Nick
--
Nick Payne
Developer
SBsquared Limited
The Old Forge
Hoults Estate
Walker Road
Newcastle upon Tyne
NE6 1AB
T: +44(0)845 330 7201
F: +44(0)870 460 4937
W: www.sbsquared.com
--------------090308010305020907040808
Content-Type: text/x-patch;
name="smarty.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="smarty.diff"
1838a1839,1841
>
> static $_cache_info = array();
>
1847a1851,1899
>
> $cache = $params['smarty_include_vars']['cache'];
> unset($params['smarty_include_vars']['cache']);
>
> //If caching check for cache, and return if found
> if($cache != "") {
> /* save cache lifetime */
> $_cache_lifetime = $this->cache_lifetime;
>
> /* set to $cache */
> $this->cache_lifetime = $cache;
>
> $resource_name = $params['smarty_include_tpl_file'];
>
> // save old cache_info, initialize cache_info
> array_push($_cache_info, $this->_cache_info);
> $this->_cache_info = array();
> $_params = array(
> 'tpl_file' => $resource_name,
> 'cache_id' => '',
> 'compile_id' => '',
> 'results' => "",
> );
>
> require_once(SMARTY_CORE_DIR . 'core.read_cache_file.php');
> if (smarty_core_read_cache_file($_params, $this)) {
> $_smarty_results = $_params['results'];
> if (!empty($this->_cache_info['insert_tags'])) {
> $_params = array('plugins' => $this->_cache_info['insert_tags']);
> require_once(SMARTY_CORE_DIR . 'core.load_plugins.php');
> smarty_core_load_plugins($_params, $this);
> $_params = array('results' => $_smarty_results);
> require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
> $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
> }
> if (!empty($this->_cache_info['cache_serials'])) {
> $_params = array('results' => $_smarty_results);
> require_once(SMARTY_CORE_DIR . 'core.process_compiled_include.php');
> $_smarty_results = smarty_core_process_compiled_include($_params, $this);
> }
> echo $_smarty_results;
> return true;
> }
>
> //ASSERT NO CACHE
> $this->_cache_info['template'][$resource_name] = true;
> }
>
> //Normal Behaviour
1861,1863c1913,1948
< include($_smarty_compile_path);
< }
<
---
> if($cache != "") {
> /* save output buffer for later */
> $ob_pre = ob_get_contents();
> ob_end_clean();
> ob_start();
> }
> include($_smarty_compile_path);
> if($cache != "") {
> /* save output buffer into cache */
> $_params["results"] = ob_get_contents();
> ob_end_clean();
> ob_start();
> /* restore original output buffer */
> echo $ob_pre;
> }
>
> }
>
>
> if($cache != "") {
>
> /* write cache file */
> require_once(SMARTY_CORE_DIR . 'core.write_cache_file.php');
> smarty_core_write_cache_file($_params, $this);
> require_once(SMARTY_CORE_DIR . 'core.process_cached_inserts.php');
> $_smarty_results = smarty_core_process_cached_inserts($_params, $this);
>
> // restore initial cache_info
> $this->_cache_info = array_pop($_cache_info);
> $this->cache_lifetime = $_cache_lifetime;
>
> //actually output data this run
> echo $_smarty_results;
> return true;
> }
>
--------------090308010305020907040808--