Dec 27 2008

Symfony класс myCache для кеширования пользовательских данных

Category: Symfonyingvar @ 23:46

Для кеширования своих пользовательских данных был написан класс 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/

Tags:

10 Responses to “Symfony класс myCache для кеширования пользовательских данных”

  1. Pentium133 says:

    Неплохо бы было расширить класс поддержкой тегов как сделал я http://codepad.org/G2ucGkt4

    • broderix says:

      В symfony в sfCache есть метод removePattern, который частично решает вопрос с тегами.

      abstract class sfCache
      {
      public function removePattern($pattern)
      {

      }

      }

  2. ingvar says:

    Задумка хорошая, но мне нравиться реализация в Zend_Cache, где есть создание/удаление по тегам.

  3. Нат says:

    Хм.. раньше таким не занимался, за класс шпасибо :)
    А почему не использовать Zend_Cache? это в качестве гипотезы. Bridge на автоподгрузку классов — пять строчек в конфигурации проекта, из зенда можно взять только то, что необходимо для поддержки кэша.
    Хотя… мне самому эта идея уже не нравится по причине того, что оно все-таки уже написано в sf* классах.

    Допишете реализацию с тэгами и попробуете отправить патч?)

  4. ingvar says:

    Zend_Cache не хотел использовать, т.к. тут есть весь необходимый функционал, которого мне хватало на решение задач. Как быстрое решение проблемы Zend_Cache подходит на ура. А на счет тегов, как допишу в скором времени сообщу :).

  5. Yura says:

    А клін чому не статік?
    Я в себе виправи на таке

    public static function clean($mode = sfCache::ALL)
    {
    return self::getInstance()->clean($mode);
    }

  6. Anatoly Pashin says:

    Может кому-то будет полезно — возможность не писать в 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');

    • Anatoly Pashin says:

      По поводу тегов: в симфонии используется древовидная структура кеша из неймспейсов (как в sfUser->(get|set)Attribute)
      Например, у вас есть новости и комментарии к ним.

      Структура кеша:
      новости:идентификатор-новости:идентификатор-комментария

      Симфония заменяет «:» (по-умолчанию) на DIRECTORY_SEPARATOR и removePattern понимает вилдкарды: * — один неймспейс, ** — один и более (вложеные неймспесы+сепаратор):
      removePattern(‘news:*:last’) вырежет все ‘last’ из каждой новости.

      В большинстве случаев этого достаточно.

Leave a Reply to ingvar