W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
Smarty默認(rèn)是使用基于文件的緩存機(jī)制,作為可選的方案,你可以自定義一套緩存機(jī)制的實(shí)現(xiàn),來(lái)進(jìn)行緩存文件的讀寫(xiě)和刪除。
Smarty2使用$cache_handler_func
的回調(diào)函數(shù)來(lái)實(shí)現(xiàn)此功能。 而Smarty3使用了Smarty_CacheResource
模塊來(lái)實(shí)現(xiàn)。
自定義緩存實(shí)現(xiàn)可以實(shí)現(xiàn)類似下面的目的: 用更快的存儲(chǔ)引擎來(lái)替代較慢的文件系統(tǒng), 使緩存可以分布到多臺(tái)服務(wù)器上。
Smarty可以通過(guò)API Smarty_CacheResource_Custom
或者Smarty_CacheResource_KeyValueStore
來(lái)實(shí)現(xiàn)緩存機(jī)制。Smarty_CacheResource_Custom
是比較簡(jiǎn)單的API,直接通過(guò)覆蓋讀、寫(xiě)、刪除等操作來(lái)實(shí)現(xiàn)緩存機(jī)制。 該API可以使用于任何你覺(jué)得適合的方式,或存儲(chǔ)到任何你覺(jué)得適合的地方。Smarty_CacheResource_KeyValueStore
的API可讓你使用K-V存儲(chǔ)模式(比如APC,Memcache等)來(lái)實(shí)現(xiàn)緩存機(jī)制。 更進(jìn)一步,就算是多層的緩存組如"a|b|c",該API也讓你可以通過(guò)刪除緩存組"a"來(lái)將整個(gè)嵌套的緩存組刪除, 即使K-V存儲(chǔ)機(jī)制本身無(wú)法實(shí)現(xiàn)這種層次結(jié)構(gòu)的存儲(chǔ)。
自定義緩存可以放到$plugins_dir
目錄下并命名為cacheresource.foobarxyz.php
, 或者在運(yùn)行時(shí)通過(guò)registerCacheResource()
來(lái)進(jìn)行注冊(cè)。 上面兩種方式都必須設(shè)置$caching_type
來(lái)啟動(dòng)你的自定義緩存機(jī)制。
Example 15.15. 通過(guò)MySQL實(shí)現(xiàn)自定義緩存機(jī)制
<?php require_once 'libs/Smarty.class.php'; $smarty = new Smarty(); $smarty->caching_type = 'mysql'; /** * MySQL 緩存 * * 通過(guò)自定義緩存的接口API,讓MySQL來(lái)作為Smarty的輸出緩存存儲(chǔ)器。 * * 表定義: * <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 對(duì)象 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 源無(wú)法鏈接: ' . $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)'); } /** * 從數(shù)據(jù)表中獲取緩存的內(nèi)容及修改時(shí)間 * * @param string $id 緩存內(nèi)容的唯一識(shí)別ID * @param string $name 模板名稱 * @param string $cache_id 緩存ID * @param string $compile_id 編譯ID * @param string $content (引用的)緩存內(nèi)容 * @param integer $mtime 緩存修改的時(shí)間戳 (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; } } /** * 從數(shù)據(jù)表中獲取緩存的修改時(shí)間 * * @note 這是個(gè)可選的實(shí)現(xiàn)接口。在你確定僅獲取修改時(shí)間會(huì)比獲取整個(gè)內(nèi)容要更快的時(shí)候,使用此接口。 * @param string $id 緩存內(nèi)容的唯一識(shí)別ID * @param string $name 模板名稱 * @param string $cache_id 緩存ID * @param string $compile_id 編譯ID * @return integer|boolean 返回模板修改時(shí)間,如果找不到緩存則返回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; } /** * 保存緩存內(nèi)容到數(shù)據(jù)表 * * @param string $id 緩存內(nèi)容的唯一識(shí)別ID * @param string $name 模板名稱 * @param string $cache_id 緩存ID * @param string $compile_id 編譯ID * @param integer|null $exp_time 緩存過(guò)期時(shí)間,或null * @param string $content 需要緩存的內(nèi)容 * @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(); } /** * 從數(shù)據(jù)表中刪除緩存 * * @param string $name 模板名稱 * @param string $cache_id 緩存ID * @param string $compile_id 編譯ID * @param integer|null $exp_time 緩存過(guò)期時(shí)間,或null * @return integer 返回被刪除的緩存數(shù)量 */ protected function delete($name, $cache_id, $compile_id, $exp_time) { // 刪除整個(gè)緩存 if ($name === null && $cache_id === null && $compile_id === null && $exp_time === null) { // 返回刪除緩存記錄的數(shù)量,需要再進(jìn)行一次查詢來(lái)計(jì)算。 $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); } // 匹配過(guò)期時(shí)間范圍 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 .'|%') .')'; } // 執(zhí)行刪除 $query = $this->db->query('DELETE FROM output_cache WHERE ' . join(' AND ', $where)); return $query->rowCount(); } } ?>
Example 15.16. 通過(guò)Memcache實(shí)現(xiàn)自定義緩存機(jī)制
<?php require_once 'libs/Smarty.class.php'; $smarty = new Smarty(); $smarty->caching_type = 'memcache'; /** * Memcache 緩存 * * 通過(guò)K-V存儲(chǔ)的API來(lái)把memcache作為Smarty的輸出緩存器。 * * 注意memcache要求key的長(zhǎng)度只能是256個(gè)字符以內(nèi), * 所以程序中,key都進(jìn)行sha1哈希計(jì)算后才使用。 * * @package CacheResource-examples * @author Rodney Rehm */ class Smarty_CacheResource_Memcache extends Smarty_CacheResource_KeyValueStore { /** * memcache 對(duì)象 * @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 多個(gè)key * @return array 按key的順序返回的對(duì)應(yīng)值 * @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對(duì)應(yīng)的值存儲(chǔ)到memcache中。 * * @param array $keys 多個(gè)kv對(duì)應(yīng)的數(shù)據(jù)值 * @param int $expire 過(guò)期時(shí)間 * @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 待刪除的多個(gè)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(); } } ?>
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: