Для кеширования своих пользовательских данных был написан класс myCache. Это всего лишь обертка к существующим классам кеширования Symfony (File, APC, XCache, EAccelerator, SQLite). С помощью настроек в app.yml есть возможность настроить кеширование, указав какой механизм использовать. В чем удобство? В любой момент можно изменить, что использовать для кеширования, и весь код переписывать не требуется под конкретный класс (например, sfEAcceleratorCache или sfAPCCache). Плюс, если к примеру использовать APC, а он не установлен, то будет активирован File. Файл разместить в папку ‘/lib/myCache.class.php’.
Листинг 1: настройка класса
[app.yml] all: my_cache: class: sfFileCache # sfFileCache, sfAPCCache, sfXCacheCache, sfEAcceleratorCache, sfSQLiteCache param: automatic_cleaning_factor: 0 cache_dir: %SF_APP_CACHE_DIR%/my lifetime: 86400 prefix: %SF_APP_DIR%/cache_my
Листинг 2: класс myCache.class.php. Скачать myCache.class.phps
<?php /** * Cache class that stores cached content in File, APC, XCache, EAccelerator, SQLite. * * @package symfony * @subpackage cache * @author Igor Brovchenko [Igor.Brovchenko [at] gmail.com] */ /* Usage [app.yml] all: my_cache: class: sfFileCache param: automatic_cleaning_factor: 0 cache_dir: %SF_APP_CACHE_DIR%/my lifetime: 86400 prefix: %SF_APP_DIR%/cache_my <php if(is_null($data = myCache::get('my_data'))) { myCache::set('my_data', $data); } echo $data; ?> */ class myCache { private static $cache = null; /** * Initializes this cache instance. */ private static function getInstance() { if(is_null(self::$cache)) { $options = sfConfig::get('app_my_cache_param'); $class = sfConfig::get('app_my_cache_class'); if('sfAPCCache' == $class && function_exists('apc_store')) { self::$cache = new sfAPCCache($options); } elseif('sfXCacheCache' == $class && function_exists('xcache_set')) { self::$cache = new sfXCacheCache($options); } elseif('sfEAcceleratorCache' == $class && function_exists('eaccelerator_put')) { self::$cache = new sfEAcceleratorCache($options); } elseif('sfSQLiteCache' == $class && extension_loaded('SQLite')) { self::$cache = new sfSQLiteCache($options); } else { self::$cache = new sfFileCache($options); } } return self::$cache; } /** * @see sfCache */ public static function get($key, $default = null) { $data = self::getInstance()->get($key); if($data === null) { return $default; } return unserialize($data); } /** * @see sfCache */ public static function has($key) { return self::getInstance()->has($key); } /** * @see sfCache */ public static function set($key, $data, $lifetime = null) { $data = serialize($data); return self::getInstance()->set($key, $data, $lifetime); } /** * @see sfCache */ public static function remove($key) { return self::getInstance()->remove($key); } /** * @see sfCache */ public static function removePattern($pattern) { self::getInstance()->removePattern($pattern); } /** * @see sfCache */ public static function clean($mode = sfCache::ALL) { return self::getInstance()->removePattern($mode); } /** * @see sfCache */ public static function getTimeout($key) { return self::getInstance()->getTimeout($key); } /** * @see sfCache */ public static function getLastModified($key) { return self::getInstance()->getLastModified($key); } }
Листинг 3: использование myCache.class.php
if(is_null($data = myCache::get('my_data'))) { myCache::set('my_data', $data); } echo $data;
Что можно почитать:
• http://www.symfony-project.org/book/1_2/12-Caching
• http://php.dzone.com/articles/using-sffilecache-directly
• http://redotheweb.com/2007/03/16/build-your-own-feed-aggregator-with-symfony/
Декабрь 28th, 2008 at 10:44
Неплохо бы было расширить класс поддержкой тегов как сделал я http://codepad.org/G2ucGkt4
Сентябрь 19th, 2009 at 16:00
В symfony в sfCache есть метод removePattern, который частично решает вопрос с тегами.
abstract class sfCache
{
public function removePattern($pattern)
{
…
}
…
}
Декабрь 28th, 2008 at 14:00
Задумка хорошая, но мне нравиться реализация в Zend_Cache, где есть создание/удаление по тегам.
Январь 6th, 2009 at 02:50
Хм.. раньше таким не занимался, за класс шпасибо
А почему не использовать Zend_Cache? это в качестве гипотезы. Bridge на автоподгрузку классов — пять строчек в конфигурации проекта, из зенда можно взять только то, что необходимо для поддержки кэша.
Хотя… мне самому эта идея уже не нравится по причине того, что оно все-таки уже написано в sf* классах.
Допишете реализацию с тэгами и попробуете отправить патч?)
Январь 6th, 2009 at 17:15
Zend_Cache не хотел использовать, т.к. тут есть весь необходимый функционал, которого мне хватало на решение задач. Как быстрое решение проблемы Zend_Cache подходит на ура. А на счет тегов, как допишу в скором времени сообщу :).
Июнь 29th, 2009 at 15:02
А клін чому не статік?
Я в себе виправи на таке
public static function clean($mode = sfCache::ALL)
{
return self::getInstance()->clean($mode);
}
Июнь 30th, 2009 at 08:50
Спасибо. Обновил по всем методам, где не хватало static
Август 5th, 2009 at 14:29
Memcached еще забыл завернуть
В Симфони есть клас sfMemcacheCache.class.php
Октябрь 1st, 2012 at 02:15
Может кому-то будет полезно — возможность не писать в app.yml
Меняем
$options = sfConfig::get('app_my_cache_param');
$class = sfConfig::get('app_my_cache_class');
на
$defaultOptions = array(
'automatic_cleaning_factor' => 0,
'cache_dir' => sfConfig::get('sf_app_cache_dir') . DIRECTORY_SEPARATOR . 'my',
'lifetime' => 86400,
'prefix' => sfConfig::get('sf_app_dir') . DIRECTORY_SEPARATOR . 'cache_my',
);
$options = array_merge($defaultOptions, sfConfig::get('app_my_cache_param', array()));
$class = sfConfig::get('app_my_cache_class', 'sfFileCache');
Октябрь 1st, 2012 at 02:37
По поводу тегов: в симфонии используется древовидная структура кеша из неймспейсов (как в sfUser->(get|set)Attribute)
Например, у вас есть новости и комментарии к ним.
Структура кеша:
новости:идентификатор-новости:идентификатор-комментария
Симфония заменяет «:» (по-умолчанию) на DIRECTORY_SEPARATOR и removePattern понимает вилдкарды: * — один неймспейс, ** — один и более (вложеные неймспесы+сепаратор):
removePattern(‘news:*:last’) вырежет все ‘last’ из каждой новости.
В большинстве случаев этого достаточно.