Feature/add docs (#689)

* Add converted docs repo

* Set theme jekyll-theme-minimal

* Removed BC docs, added TOC

* Added TOCs, rewrote most important links in documentation. Linked README to new Github Pages site

* some link fixes
This commit is contained in:
Simon Wisselink
2021-12-03 11:59:22 +01:00
committed by GitHub
parent baebd59bb4
commit 428a701b18
226 changed files with 13978 additions and 1 deletions

View File

@ -0,0 +1,176 @@
Controlling Cacheability of Output {#caching.cacheable}
==================================
If caching is enabled normally the whole final output of the page gets
cached. However Smarty3 offers several options how to exclude sections
of your output from caching.
> **Note**
>
> Be sure any variables used within a non-cached section are also
> assigned from PHP when the page is loaded from the cache.
Cacheability of Template Section {#cacheability.sections}
--------------------------------
A larger section of your template can easily excluded from caching by
using the [`{nocache}`](#language.function.nocache) and
[`{/nocache}`](#language.function.nocache) tags.
Today's date is
{nocache}
{$smarty.now|date_format}
{/nocache}
The above code will output the current date on a cached page.
Cacheability of Tags {#cacheability.tags}
--------------------
Caching for an individual tag can be disabled by adding the \"nocache\"
option flag to the tag.
Today's date is
{$smarty.now|date_format nocache}
Cacheability of Variables {#cacheability.variables}
-------------------------
You can [`assign()`](#api.assign) variables as not cachable. Any tag
which uses such variable will be automatically executed in nocache mode.
> **Note**
>
> If a tag is executed in nocache mode you must make sure that all other
> variables used by that tag are also assigned from PHP when the page is
> loaded from the cache.
> **Note**
>
> The nocache status of an assigned variable will effect the compiled
> template code. If you change the status you must manually delete
> existing compiled and cached template files to force a recompile.
// assign $foo as nocahe variable
$smarty->assign('foo',time(),true);
Dynamic time value is {$foo}
Cacheability of Plugins {#cacheability.plugins}
-----------------------
The cacheability of plugins can be declared when registering them. The
third parameter to [`registerPlugin()`](#api.register.plugin) is called
`$cacheable` and defaults to TRUE.
When registering a plugin with `$cacheable=false` the plugin is called
everytime the page is displayed, even if the page comes from the cache.
The plugin function behaves a little like an
[`{insert}`](#plugins.inserts) function.
> **Note**
>
> The `$cacheable` status will effect the compiled template code. If you
> change the status you must manually delete existing compiled and
> cached template files to force a recompile.
In contrast to [`{insert}`](#plugins.inserts) the attributes to the
plugins are not cached by default. They can be declared to be cached
with the fourth parameter `$cache_attrs`. `$cache_attrs` is an array of
attribute-names that should be cached, so the plugin-function get value
as it was the time the page was written to cache everytime it is fetched
from the cache.
<?php
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
function remaining_seconds($params, $smarty) {
$remain = $params['endtime'] - time();
if($remain >= 0){
return $remain . ' second(s)';
}else{
return 'done';
}
}
$smarty->registerPlugin('function','remaining', 'remaining_seconds', false, array('endtime'));
if (!$smarty->isCached('index.tpl')) {
// fetch $obj from db and assign...
$smarty->assignByRef('obj', $obj);
}
$smarty->display('index.tpl');
?>
where `index.tpl` is:
Time Remaining: {remaining endtime=$obj->endtime}
The number of seconds till the endtime of `$obj` is reached changes on
each display of the page, even if the page is cached. Since the endtime
attribute is cached the object only has to be pulled from the database
when page is written to the cache but not on subsequent requests of the
page.
index.php:
<?php
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
function smarty_block_dynamic($param, $content, $smarty) {
return $content;
}
$smarty->registerPlugin('block','dynamic', 'smarty_block_dynamic', false);
$smarty->display('index.tpl');
?>
where `index.tpl` is:
Page created: {'0'|date_format:'%D %H:%M:%S'}
{dynamic}
Now is: {'0'|date_format:'%D %H:%M:%S'}
... do other stuff ...
{/dynamic}
When reloading the page you will notice that both dates differ. One is
"dynamic" one is "static". You can do everything between
`{dynamic}...{/dynamic}` and be sure it will not be cached like the rest
of the page.
> **Note**
>
> The above example shall just demonstrate how a dynamic block plugins
> works. See
> [`Cacheability of Template Section`](#cacheability.sections) on how to
> disable caching of a template section by the built-in
> [`{nocache}`](#language.function.nocache) and
> [`{/nocache}`](#language.function.nocache) tags.

View File

@ -0,0 +1,296 @@
Custom Cache Implementation {#caching.custom}
===========================
As an alternative to using the default file-based caching mechanism, you
can specify a custom cache implementation that will be used to read,
write and clear cached files.
> **Note**
>
> In Smarty2 this used to be a callback function called
> `$cache_handler_func`. Smarty3 replaced this callback by the
> `Smarty_CacheResource` module.
With a custom cache implementation you\'re likely trying to achieve at
least one of the following goals: replace the slow filesystem by a
faster storage engine, centralize the cache to be accessible to multiple
servers.
Smarty allows CacheResource implementations to use one of the APIs
`Smarty_CacheResource_Custom` or `Smarty_CacheResource_KeyValueStore`.
`Smarty_CacheResource_Custom` is a simple API directing all read, write,
clear calls to your implementation. This API allows you to store
wherever and however you deem fit. The
`Smarty_CacheResource_KeyValueStore` API allows you to turn any \"dumb\"
KeyValue-Store (like APC, Memcache, ...) into a full-featured
CacheResource implementation. That is, everything around deep
cache-groups like \"a\|b\|c\" is being handled for you in way that
allows clearing the cache-group \"a\" and all nested groups are cleared
as well - even though KeyValue-Stores don\'t allow this kind of
hierarchy by nature.
Custom CacheResources may be put in a file `cacheresource.foobarxyz.php`
within your [`$plugins_dir`](#variable.plugins.dir), or registered on
runtime with [`registerCacheResource()`](#api.register.cacheresource).
In either case you need to set [`$caching_type`](#variable.caching.type)
to invoke your custom CacheResource implementation.
<?php
require_once 'libs/Smarty.class.php';
$smarty = new Smarty();
$smarty->caching_type = 'mysql';
/**
* MySQL CacheResource
*
* CacheResource Implementation based on the Custom API to use
* MySQL as the storage resource for Smarty's output caching.
*
* Table definition:
* <pre>CREATE TABLE IF NOT EXISTS `output_cache` (
* `id` CHAR(40) NOT NULL COMMENT 'sha1 hash',
* `name` VARCHAR(250) NOT NULL,
* `cache_id` VARCHAR(250) NULL DEFAULT NULL,
* `compile_id` VARCHAR(250) NULL DEFAULT NULL,
* `modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
* `content` LONGTEXT NOT NULL,
* PRIMARY KEY (`id`),
* INDEX(`name`),
* INDEX(`cache_id`),
* INDEX(`compile_id`),
* INDEX(`modified`)
* ) ENGINE = InnoDB;</pre>
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Mysql extends Smarty_CacheResource_Custom {
// PDO instance
protected $db;
protected $fetch;
protected $fetchTimestamp;
protected $save;
public function __construct() {
try {
$this->db = new PDO("mysql:dbname=test;host=127.0.0.1", "smarty", "smarty");
} catch (PDOException $e) {
throw new SmartyException('Mysql Resource failed: ' . $e->getMessage());
}
$this->fetch = $this->db->prepare('SELECT modified, content FROM output_cache WHERE id = :id');
$this->fetchTimestamp = $this->db->prepare('SELECT modified FROM output_cache WHERE id = :id');
$this->save = $this->db->prepare('REPLACE INTO output_cache (id, name, cache_id, compile_id, content)
VALUES (:id, :name, :cache_id, :compile_id, :content)');
}
/**
* fetch cached content and its modification time from data source
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param string $content cached content
* @param integer $mtime cache modification timestamp (epoch)
* @return void
*/
protected function fetch($id, $name, $cache_id, $compile_id, &$content, &$mtime)
{
$this->fetch->execute(array('id' => $id));
$row = $this->fetch->fetch();
$this->fetch->closeCursor();
if ($row) {
$content = $row['content'];
$mtime = strtotime($row['modified']);
} else {
$content = null;
$mtime = null;
}
}
/**
* Fetch cached content's modification timestamp from data source
*
* @note implementing this method is optional. Only implement it if modification times can be accessed faster than loading the complete cached content.
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @return integer|boolean timestamp (epoch) the template was modified, or false if not found
*/
protected function fetchTimestamp($id, $name, $cache_id, $compile_id)
{
$this->fetchTimestamp->execute(array('id' => $id));
$mtime = strtotime($this->fetchTimestamp->fetchColumn());
$this->fetchTimestamp->closeCursor();
return $mtime;
}
/**
* Save content to cache
*
* @param string $id unique cache content identifier
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param integer|null $exp_time seconds till expiration time in seconds or null
* @param string $content content to cache
* @return boolean success
*/
protected function save($id, $name, $cache_id, $compile_id, $exp_time, $content)
{
$this->save->execute(array(
'id' => $id,
'name' => $name,
'cache_id' => $cache_id,
'compile_id' => $compile_id,
'content' => $content,
));
return !!$this->save->rowCount();
}
/**
* Delete content from cache
*
* @param string $name template name
* @param string $cache_id cache id
* @param string $compile_id compile id
* @param integer|null $exp_time seconds till expiration or null
* @return integer number of deleted caches
*/
protected function delete($name, $cache_id, $compile_id, $exp_time)
{
// delete the whole cache
if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
// returning the number of deleted caches would require a second query to count them
$query = $this->db->query('TRUNCATE TABLE output_cache');
return -1;
}
// build the filter
$where = array();
// equal test name
if ($name !== null) {
$where[] = 'name = ' . $this->db->quote($name);
}
// equal test compile_id
if ($compile_id !== null) {
$where[] = 'compile_id = ' . $this->db->quote($compile_id);
}
// range test expiration time
if ($exp_time !== null) {
$where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
}
// equal test cache_id and match sub-groups
if ($cache_id !== null) {
$where[] = '(cache_id = '. $this->db->quote($cache_id)
. ' OR cache_id LIKE '. $this->db->quote($cache_id .'|%') .')';
}
// run delete query
$query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
return $query->rowCount();
}
}
<?php
require_once 'libs/Smarty.class.php';
$smarty = new Smarty();
$smarty->caching_type = 'memcache';
/**
* Memcache CacheResource
*
* CacheResource Implementation based on the KeyValueStore API to use
* memcache as the storage resource for Smarty's output caching.
*
* Note that memcache has a limitation of 256 characters per cache-key.
* To avoid complications all cache-keys are translated to a sha1 hash.
*
* @package CacheResource-examples
* @author Rodney Rehm
*/
class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore {
/**
* memcache instance
* @var Memcache
*/
protected $memcache = null;
public function __construct()
{
$this->memcache = new Memcache();
$this->memcache->addServer( '127.0.0.1', 11211 );
}
/**
* Read values for a set of keys from cache
*
* @param array $keys list of keys to fetch
* @return array list of values with the given keys used as indexes
* @return boolean true on success, false on failure
*/
protected function read(array $keys)
{
$_keys = $lookup = array();
foreach ($keys as $k) {
$_k = sha1($k);
$_keys[] = $_k;
$lookup[$_k] = $k;
}
$_res = array();
$res = $this->memcache->get($_keys);
foreach ($res as $k => $v) {
$_res[$lookup[$k]] = $v;
}
return $_res;
}
/**
* Save values for a set of keys to cache
*
* @param array $keys list of values to save
* @param int $expire expiration time
* @return boolean true on success, false on failure
*/
protected function write(array $keys, $expire=null)
{
foreach ($keys as $k => $v) {
$k = sha1($k);
$this->memcache->set($k, $v, 0, $expire);
}
return true;
}
/**
* Remove values from cache
*
* @param array $keys list of keys to delete
* @return boolean true on success, false on failure
*/
protected function delete(array $keys)
{
foreach ($keys as $k) {
$k = sha1($k);
$this->memcache->delete($k);
}
return true;
}
/**
* Remove *all* values from cache
*
* @return boolean true on success, false on failure
*/
protected function purge()
{
return $this->memcache->flush();
}
}

View File

@ -0,0 +1,60 @@
Cache Groups {#caching.groups}
============
You can do more elaborate grouping by setting up `$cache_id` groups.
This is accomplished by separating each sub-group with a vertical bar
`|` in the `$cache_id` value. You can have as many sub-groups as you
like.
- You can think of cache groups like a directory hierarchy. For
instance, a cache group of `'a|b|c'` could be thought of as the
directory structure `'/a/b/c/'`.
- `clearCache(null,'a|b|c')` would be like removing the files
`'/a/b/c/*'`. `clearCache(null,'a|b')` would be like removing the
files `'/a/b/*'`.
- If you specify a [`$compile_id`](#variable.compile.id) such as
`clearCache(null,'a|b','foo')` it is treated as an appended cache
group `'/a/b/c/foo/'`.
- If you specify a template name such as
`clearCache('foo.tpl','a|b|c')` then Smarty will attempt to remove
`'/a/b/c/foo.tpl'`.
- You CANNOT remove a specified template name under multiple cache
groups such as `'/a/b/*/foo.tpl'`, the cache grouping works
left-to-right ONLY. You will need to group your templates under a
single cache group heirarchy to be able to clear them as a group.
Cache grouping should not be confused with your template directory
heirarchy, the cache grouping has no knowledge of how your templates are
structured. So for example, if you have a template structure like
`themes/blue/index.tpl` and you want to be able to clear all the cache
files for the "blue" theme, you will need to create a cache group
structure that mimics your template file structure, such as
`display('themes/blue/index.tpl','themes|blue')`, then clear them with
`clearCache(null,'themes|blue')`.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// clear all caches with 'sports|basketball' as the first two cache_id groups
$smarty->clearCache(null,'sports|basketball');
// clear all caches with "sports" as the first cache_id group. This would
// include "sports|basketball", or "sports|(anything)|(anything)|(anything)|..."
$smarty->clearCache(null,'sports');
// clear the foo.tpl cache file with "sports|basketball" as the cache_id
$smarty->clearCache('foo.tpl','sports|basketball');
$smarty->display('index.tpl','sports|basketball');
?>

View File

@ -0,0 +1,87 @@
Multiple Caches Per Page {#caching.multiple.caches}
========================
You can have multiple cache files for a single call to
[`display()`](#api.display) or [`fetch()`](#api.fetch). Let\'s say that
a call to `display('index.tpl')` may have several different output
contents depending on some condition, and you want separate caches for
each one. You can do this by passing a `$cache_id` as the second
parameter to the function call.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$my_cache_id = $_GET['article_id'];
$smarty->display('index.tpl', $my_cache_id);
?>
Above, we are passing the variable `$my_cache_id` to
[`display()`](#api.display) as the `$cache_id`. For each unique value of
`$my_cache_id`, a separate cache will be generated for `index.tpl`. In
this example, `article_id` was passed in the URL and is used as the
`$cache_id`.
> **Note**
>
> Be very cautious when passing values from a client (web browser) into
> Smarty or any PHP application. Although the above example of using the
> article\_id from the URL looks handy, it could have bad consequences.
> The `$cache_id` is used to create a directory on the file system, so
> if the user decided to pass an extremely large value for article\_id,
> or write a script that sends random article\_id\'s at a rapid pace,
> this could possibly cause problems at the server level. Be sure to
> sanitize any data passed in before using it. In this instance, maybe
> you know the article\_id has a length of ten characters and is made up
> of alpha-numerics only, and must be a valid article\_id in the
> database. Check for this!
Be sure to pass the same `$cache_id` as the second parameter to
[`isCached()`](#api.is.cached) and [`clearCache()`](#api.clear.cache).
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$my_cache_id = $_GET['article_id'];
if(!$smarty->isCached('index.tpl',$my_cache_id)) {
// No cache available, do variable assignments here.
$contents = get_database_contents();
$smarty->assign($contents);
}
$smarty->display('index.tpl',$my_cache_id);
?>
You can clear all caches for a particular `$cache_id` by passing NULL as
the first parameter to [`clearCache()`](#api.clear.cache).
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// clear all caches with "sports" as the $cache_id
$smarty->clearCache(null,'sports');
$smarty->display('index.tpl','sports');
?>
In this manner, you can "group" your caches together by giving them the
same `$cache_id`.

View File

@ -0,0 +1,153 @@
Setting Up Caching {#caching.setting.up}
==================
The first thing to do is enable caching by setting
[`$caching`](#variable.caching) to one of
`Smarty::CACHING_LIFETIME_CURRENT` or `Smarty::CACHING_LIFETIME_SAVED`.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
// uses the value of $smarty->cacheLifetime() to determine
// the number of seconds a cache is good for
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$smarty->display('index.tpl');
?>
With caching enabled, the function call to `display('index.tpl')` will
render the template as usual, but also saves a copy of its output to a
file (a cached copy) in the [`$cache_dir`](#variable.cache.dir). On the
next call to `display('index.tpl')`, the cached copy will be used
instead of rendering the template again.
> **Note**
>
> The files in the [`$cache_dir`](#variable.cache.dir) are named similar
> to the template name. Although they end in the `.php` extension, they
> are not intended to be directly executable. Do not edit these files!
Each cached page has a limited lifetime determined by
[`$cache_lifetime`](#variable.cache.lifetime). The default value is 3600
seconds, or one hour. After that time expires, the cache is regenerated.
It is possible to give individual caches their own expiration time by
setting [`$caching`](#variable.caching) to
`Smarty::CACHING_LIFETIME_SAVED`. See
[`$cache_lifetime`](#variable.cache.lifetime) for more details.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
// retain current cache lifetime for each specific display call
$smarty->setCaching(Smarty::CACHING_LIFETIME_SAVED);
// set the cache_lifetime for index.tpl to 5 minutes
$smarty->setCacheLifetime(300);
$smarty->display('index.tpl');
// set the cache_lifetime for home.tpl to 1 hour
$smarty->setCacheLifetime(3600);
$smarty->display('home.tpl');
// NOTE: the following $cache_lifetime setting will not work when $caching
// is set to Smarty::CACHING_LIFETIME_SAVED.
// The cache lifetime for home.tpl has already been set
// to 1 hour, and will no longer respect the value of $cache_lifetime.
// The home.tpl cache will still expire after 1 hour.
$smarty->setCacheLifetime(30); // 30 seconds
$smarty->display('home.tpl');
?>
If [`$compile_check`](#variable.compile.check) is enabled (default),
every template file and config file that is involved with the cache file
is checked for modification. If any of the files have been modified
since the cache was generated, the cache is immediately regenerated.
This is a computational overhead, so for optimum performance set
[`$compile_check`](#variable.compile.check) to FALSE.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
$smarty->setCompileCheck(false);
$smarty->display('index.tpl');
?>
If [`$force_compile`](#variable.force.compile) is enabled, the cache
files will always be regenerated. This effectively disables caching,
however this also seriously degrades performance.
[`$force_compile`](#variable.force.compile) is meant to be used for
[debugging](#chapter.debugging.console) purposes. The appropriate way to
disable caching is to set [`$caching`](#variable.caching) to
Smarty::CACHING\_OFF.
The [`isCached()`](#api.is.cached) function can be used to test if a
template has a valid cache or not. If you have a cached template that
requires something like a database fetch, you can use this to skip that
process.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
if(!$smarty->isCached('index.tpl')) {
// No cache available, do variable assignments here.
$contents = get_database_contents();
$smarty->assign($contents);
}
$smarty->display('index.tpl');
?>
You can keep parts of a page dynamic (disable caching) with the
[`{nocache}{/nocache}`](#language.function.nocache) block function, the
[`{insert}`](#language.function.insert) function, or by using the
`nocache` parameter for most template functions.
Let\'s say the whole page can be cached except for a banner that is
displayed down the side of the page. By using the
[`{insert}`](#language.function.insert) function for the banner, you can
keep this element dynamic within the cached content. See the
documentation on [`{insert}`](#language.function.insert) for more
details and examples.
You can clear all the cache files with the
[`clearAllCache()`](#api.clear.all.cache) function, or individual cache
files [and groups](#caching.groups) with the
[`clearCache()`](#api.clear.cache) function.
<?php
require('Smarty.class.php');
$smarty = new Smarty;
$smarty->setCaching(Smarty::CACHING_LIFETIME_CURRENT);
// clear only cache for index.tpl
$smarty->clearCache('index.tpl');
// clear out all cache files
$smarty->clearAllCache();
$smarty->display('index.tpl');
?>