自定义缓存实现
Smarty默认是使用基于文件的缓存机制,作为可选的方案,你可以自定义一套缓存机制的实现,来进行缓存文件的读写和删除。
Note
Smarty2使用$cache_handler_func
的回调函数来实现此功能。 而Smarty3使用了Smarty_CacheResource
模块来实现。
自定义缓存实现可以实现类似下面的目的: 用更快的存储引擎来替代较慢的文件系统, 使缓存可以分布到多台服务器上。
Smarty可以通过API Smarty_CacheResource_Custom
或者 Smarty_CacheResource_KeyValueStore
来实现缓存机制。 Smarty_CacheResource_Custom
是比较简单的API,直接通过覆盖读、写、删除等操作来实现缓存机制。 该API可以使用于任何你觉得适合的方式,或存储到任何你觉得适合的地方。 Smarty_CacheResource_KeyValueStore
的API可让你使用K-V存储模式(比如APC,Memcache等)来实现缓存机制。 更进一步,就算是多层的缓存组如"a|b|c",该API也让你可以通过删除缓存组"a"来将整个嵌套的缓存组删除, 即使K-V存储机制本身无法实现这种层次结构的存储。
自定义缓存可以放到$plugins_dir
目录下并命名为cacheresource.foobarxyz.php
, 或者在运行时通过registerCacheResource()
来进行注册。 上面两种方式都必须设置$caching_type
来启动你的自定义缓存机制。
Example 15.15. 通过MySQL实现自定义缓存机制
- <?php
- require_once 'libs/Smarty.class.php';
- $smarty = new Smarty();
- $smarty->caching_type = 'mysql';
- /**
- * MySQL 缓存
- *
- * 通过自定义缓存的接口API,让MySQL来作为Smarty的输出缓存存储器。
- *
- * 表定义:
- * <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 对象
- 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 源无法链接: ' . $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)');
- }
- /**
- * 从数据表中获取缓存的内容及修改时间
- *
- * @param string $id 缓存内容的唯一识别ID
- * @param string $name 模板名称
- * @param string $cache_id 缓存ID
- * @param string $compile_id 编译ID
- * @param string $content (引用的)缓存内容
- * @param integer $mtime 缓存修改的时间戳 (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;
- }
- }
- /**
- * 从数据表中获取缓存的修改时间
- *
- * @note 这是个可选的实现接口。在你确定仅获取修改时间会比获取整个内容要更快的时候,使用此接口。
- * @param string $id 缓存内容的唯一识别ID
- * @param string $name 模板名称
- * @param string $cache_id 缓存ID
- * @param string $compile_id 编译ID
- * @return integer|boolean 返回模板修改时间,如果找不到缓存则返回false
- */
- 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;
- }
- /**
- * 保存缓存内容到数据表
- *
- * @param string $id 缓存内容的唯一识别ID
- * @param string $name 模板名称
- * @param string $cache_id 缓存ID
- * @param string $compile_id 编译ID
- * @param integer|null $exp_time 缓存过期时间,或null
- * @param string $content 需要缓存的内容
- * @return boolean 成功true,失败false
- */
- 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();
- }
- /**
- * 从数据表中删除缓存
- *
- * @param string $name 模板名称
- * @param string $cache_id 缓存ID
- * @param string $compile_id 编译ID
- * @param integer|null $exp_time 缓存过期时间,或null
- * @return integer 返回被删除的缓存数量
- */
- protected function delete($name, $cache_id, $compile_id, $exp_time)
- {
- // 删除整个缓存
- if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) {
- // 返回删除缓存记录的数量,需要再进行一次查询来计算。
- $query = $this->db->query('TRUNCATE TABLE output_cache');
- return -1;
- }
- // 组成查找条件
- $where = array();
- // 匹配名称
- if ($name !== null) {
- $where[] = 'name = ' . $this->db->quote($name);
- }
- // 匹配编译ID
- if ($compile_id !== null) {
- $where[] = 'compile_id = ' . $this->db->quote($compile_id);
- }
- // 匹配过期时间范围
- if ($exp_time !== null) {
- $where[] = 'modified < DATE_SUB(NOW(), INTERVAL ' . intval($exp_time) . ' SECOND)';
- }
- // 匹配缓存ID和缓存组的子ID
- if ($cache_id !== null) {
- $where[] = '(cache_id = '. $this->db->quote($cache_id)
- . ' OR cache_id LIKE '. $this->db->quote($cache_id .'|%') .')';
- }
- // 执行删除
- $query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where));
- return $query->rowCount();
- }
- }
- ?>
Example 15.16. 通过Memcache实现自定义缓存机制
- <?php
- require_once 'libs/Smarty.class.php';
- $smarty = new Smarty();
- $smarty->caching_type = 'memcache';
- /**
- * Memcache 缓存
- *
- * 通过K-V存储的API来把memcache作为Smarty的输出缓存器。
- *
- * 注意memcache要求key的长度只能是256个字符以内,
- * 所以程序中,key都进行sha1哈希计算后才使用。
- *
- * @package CacheResource-examples
- * @author Rodney Rehm
- */
- class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore {
- /**
- * memcache 对象
- * @var Memcache
- */
- protected $memcache = null;
- public function __construct()
- {
- $this->memcache = new Memcache();
- $this->memcache->addServer( '127.0.0.1', 11211 );
- }
- /**
- * 从memcache中获取一系列key的值。
- *
- * @param array $keys 多个key
- * @return array 按key的顺序返回的对应值
- * @return boolean 成功返回true,失败返回false
- */
- 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;
- }
- /**
- * 将一系列的key对应的值存储到memcache中。
- *
- * @param array $keys 多个kv对应的数据值
- * @param int $expire 过期时间
- * @return boolean 成功返回true,失败返回false
- */
- protected function write(array $keys, $expire=null)
- {
- foreach ($keys as $k => $v) {
- $k = sha1($k);
- $this->memcache->set($k, $v, 0, $expire);
- }
- return true;
- }
- /**
- * 从memcache中删除
- *
- * @param array $keys 待删除的多个key
- * @return boolean 成功返回true,失败返回false
- */
- protected function delete(array $keys)
- {
- foreach ($keys as $k) {
- $k = sha1($k);
- $this->memcache->delete($k);
- }
- return true;
- }
- /**
- * 清空全部的值
- *
- * @return boolean 成功返回true,失败返回false
- */
- protected function purge()
- {
- return $this->memcache->flush();
- }
- }
- ?>