Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "cache"

Generate admin generator module cache from anywhere

Sometimes you'd like to use partial from auto-generated module, like list partial, to keep list presentation unified.

But, before using partial, you add to be sure that cache has been generated or your application will be broken.

This little method (you can place in your tools.class.php) check that cache exists, and if not, generate it.

public static function generateAdminGeneratorModuleCache($module, $configuration)
{
  if(!($configuration instanceof sfApplicationConfiguration)) {
    throw new sfConfigurationException('You must provide a valid application configuration object');
  }
  if(!file_exists(sfConfig::get('sf_app_module_dir').DIRECTORY_SEPARATOR.$module)) {
    throw new sfConfigurationException('The module specified does not exists for this application');
  }
  if(!file_exists(sfConfig::get('sf_app_module_dir').DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'generator.yml')) {
    throw new sfConfigurationException('This module does not seems to be a valid admin generator module');
  }
  if(!file_exists(sfConfig::get('sf_module_cache_dir').DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.'actions'.DIRECTORY_SEPARATOR.'actions.class.php')) {
    // Init generator manager
    $generator_manager = new sfGeneratorManager($configuration);
    $config = sfYaml::load(sfConfig::get('sf_app_module_dir').DIRECTORY_SEPARATOR.$module.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'generator.yml');
    $config['generator']['param']['moduleName'] = $module;
    $generator_manager->generate($config['generator']['class'], $config['generator']['param']);
  }
}
 

Now you can call it from any actions with

myTools::generateAdminGeneratorModuleCache('my_module',$this->getContext()->getConfiguration());
 
by netounet on 2011-03-15, tagged cache  generator 

Controlling HTTP Caching (Squid, Varnish, ..) with cache.yml files

In this snippet I will demonstrate how to extend the sfCache interface in order to configure your template cache to use a HTTP cache proxy like Squid or Varnish.

The goal

Setting configurable headers for HTTP caches using the symfony caching system.

The implementation

somehow < and > get escaped in the following code...

  1 &lt;?php
  2
  3 /**
  4  * Cache class that sets HTTP cache headers.
  5  *
  6  * @package    symfony-snippets
  7  * @subpackage cache
  8  * @author     Christian Schaefer &lt;caefer@ical.ly&gt;
  9  * @version    SVN: $Id: $
 10  */
 11 class csHttpCacheHeaderCache extends sfCache
 12 {
 13   /**
 14    * @var headers HTTP headers to be set
 15    */
 16   private $headers = array();
 17
 18  /**
 19   * Initializes this sfCache instance.
 20   *
 21   * Available options:
 22   *
 23   * * headers:  HTTP headers to be set (array)
 24   *
 25   * * see sfCache for options available for all drivers
 26   *
 27   * @see sfCache
 28   */
 29   public function initialize($options = array())
 30   {
 31     parent::initialize($options);
 32
 33     if (!$this-&gt;getOption(&#039;headers&#039;))
 34     {
 35       throw new sfInitializationException(&#039;You must pass a &quot;headers&quot; option to initialize a gujSquidCache object.&#039;);
 36     }
 37
 38     $this-&gt;headers = $this-&gt;getOption(&#039;headers&#039;);
 39   }
 40
 41   /**
 42    * @see sfCache
 43    */
 44   public function get($key, $default = null)
 45   {
 46     return $default;
 47   }
 48
 49   /**
 50    * @see sfCache
 51    */
 52   public function has($key)
 53   {
 54     return false;
 55   }
 56
 57   /**
 58    * @see sfCache
 59    */
 60   public function set($key, $data, $lifetime = null)
 61   {
 62     if(false === strpos($key, &#039;/_partial/&#039;))  // don&#039;t set cache headers for partials
 63     {
 64       if(is_object(unserialize($data)))       // don&#039;t set cache headers for pages without layout
 65       {
 66         $response = sfContext::getInstance()-&gt;getResponse();
 67
 68         foreach($this-&gt;headers as $key =&gt; $value)
 69         {
 70           $value = str_replace(&#039;%EXPIRE_TIME%&#039;, gmdate(&quot;D, d M Y H:i:s&quot;, time() + $lifetime), $value);
 71           $value = str_replace(&#039;%LAST_MODIFIED%&#039;, gmdate(&quot;D, d M Y H:i:s&quot;, time()), $value);
 72           $value = str_replace(&#039;%LIFETIME%&#039;, $lifetime, $value);
 73           $response-&gt;setHttpHeader($key, $value, true);
 74         }
 75       }
 76     }
 77     return true;
 78   }
 79
 80   /**
 81    * @see sfCache
 82    */
 83   public function remove($key)
 84   {
 85     return true;
 86   }
 87
 88   /**
 89    * @see sfCache
 90    */
 91   public function removePattern($pattern)
 92   {
 93     return true;
 94   }
 95
 96   /**
 97    * @see sfCache
 98    */
 99   public function clean($mode = sfCache::ALL)
100   {
101     return true;
102   }
103
104   /**
105    * @see sfCache
106    */
107   public function getLastModified($key)
108   {
109     return 0;
110   }
111
112   /**
113    * @see sfCache
114    */
115   public function getTimeout($key)
116   {
117     return 0;
118   }
119 }
 

The cache class csHttpCacheHeaderCache is basically a copy of sfNoCache exept for the method set() which sets the configured headers for action templates with layout.

The configuration

In your /apps/&lt;appname&gt;/config/factories.yml configure csHttpCacheHeaderCache as your view cache class and customize any number of headers:

1 all:
2   view_cache:
3     class:    csHttpCacheHeaderCache
4     param:
5       headers:
6         Expires:        &quot;%EXPIRE_TIME%&quot;
7         Last-Modified:  &quot;%LAST_MODIFIED%&quot;
8         Cache-Control:  &quot;public&quot;
 

the placeholders %EXPIRE_TIME%, %LAST_MODIFIED% and %LIFETIME% will be dynamically replaced.

Now you can follow the symfony caching chapter in the documentation to enable caching per site or globally.

Have fun!

/Christian

by Christian Schaefer on 2009-10-16, tagged cache 
(1 comment)

Clear the cache without symfony cli and cross applications

Just use the '**' pattern with sfFileCache :

$frontend_cache_dir = sfConfig::get('sf_cache_dir').'/frontend/prod/template';
$cache = new sfFileCache(array('cache_dir' => $frontend_cache_dir)); // Use the same settings as the ones defined in the frontend factories.yml
$cache->removePattern('**'); // remove everything in the dir
 
by Damien ALEXANDRE on 2009-10-09, tagged cache  clear 
(1 comment)

Image cache to get any version of an image.

<?php
    /**
     * IMAGECACHE
     *
     * Image-cache script to convert and store images on-the-fly to any size.
     * (c) k at isr.hu
     *
     * THE PROBLEM
     *
     * You upload a lot of image assets to your site, but will need 
     * several sizes of them for various reasons. For example You'll need a big 
     * resolution version for downloading (original), also a smaller for previewing 
     * to the visitors and even another for an image-list page.
     *
     * This script will create any version of the image using imagemagick and store 
     * it next to the original file. Images already generated are served without 
     * PHP, so You'll see no performance loss.
     *
     * HOW IT WORKS
     *
     * You define ImageMagick commands in this script, giving them aliases.
     * When You need an image converted, You sppecify the command in the URL of the 
     * image. If the image (of this size/version) does not exist yet, this script 
     * will generate it and save it next to the original image. The next time this 
     * image is requested, it will be served from the filesystem, without any 
     * overhead, thanks to the mod_rewrite rule You save into the image folder's 
     * .htaccess 
     *
     * Requirement: ImageMagick installed in the server. See http://www.imagemagick.org/ for information.
     * You will also need Apache with mod_rewrite.
     *
     * EXAMPLE
     *
     * Suppose You keep image assets under web/images, and have an image called greenfrog.jpg (size: 1200x1200px)
     * saved under web/images/animals/green/greenfrog.jpg. The image is accessible under
     * http://www.you.com/images/animals/green/greenfrog.jpg
     * One day You realize that You need a 180x180px version of the image on the frontpage.
     * You can upload another variation, but with this script, you can just specify the new size in the URL, like this:
     * http://www.you.com/images/animals/green/greenfrog.180x180.jpg
     *
     * To be able to do this, You will need to save a .htaccess file into the 
     * images folder (see below), plus set the ImageMagick command associated with 180x180.
     * (The reson for the latter is security: if You run any command from the URL 
     * You open the door for DOS attacks.)
     *
     * INSTALL
     *
     * - save this script to the root of the images folder
     * - create a .htaccess file next to it, with this content: 
     *
     * <IfModule mod_rewrite.c>
     *   RewriteEngine on
     *   RewriteCond %{REQUEST_FILENAME} !-f
     *   RewriteCond %{REQUEST_FILENAME} !-d
     *   RewriteRule ^(.*)$ index.php?img=$1 [L,QSA]
     * </IfModule>
     * 
     * - specify the commands You want to accept in the commands array
     * - modify the image URL-s to take advantage of the script.
     * - done :)
     *
     * SECURITY
     *
     * AFAIK all possible DOS attacks are handled (can't generate images forever),
     * plus the script takes care not allow access to files outside the 
     * directory it is saved to.
     *
     * No guarantee or warranty of any kind!
     *
     * TIP ME!
     *
     * If You find this script useful, please consider giving me a tip!
     * Just follow this link to donate: 
     * https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7030104
     **/
 
    // find the convert command
    // you can hard-code it to make the srcipt faster, example:
    // $convert = '/usr/bin/convert';
    $convert = trim(shell_exec('which convert'));
 
    // this directory
    $thisDir = dirname(__FILE__).'/';
 
    // set commands via aliases
    $commands = array(
      '120x120' => '-geometry 120x120', // convert so no dimension is larger than 120px and keep ratio. For more commands see ImageMagick's documentation
    );
 
    // die if no image is set
    if(!$img = $_GET['img']) die('no img');
 
    // make the filename safe to use
    //$img = strip_tags(htmlspecialchars($img));
    $img = trim($img);
    $img = str_replace('..', '', $img); // no going up in directory tree
 
    // get the command specified in the filename
    // example: big_green_frog.thumb150.jpg
    preg_match("/\.([^\.]*)\..{3}$/", $img, $match); // this also means no double commands (possible DOS attack)
    if(!$command = $match[1]) die('no command');
    if(!$commands[$command]) die('command does not exist');
 
    // get original filename
    // example: big_green_frog.jpg
    $imgFile = str_replace('.'.$command, '', $img, $replaceCount);
 
    // stop the possibility of creating unlimited files
    // example (attack): abc.120.jpg, abc.120.120.jpg, abc.120.....120.jpg - this could go on forever
    if($replaceCount > 1) die('command specified more than 1 time');
 
    // die if the original file does not exist
    if(!file_exists($thisDir.$imgFile)) die('original file does not exist');
 
    // prepare the command
    $preparedCommand = $convert .' '. $commands[$command] .' '. $thisDir . $imgFile .' '. $thisDir . $img;
 
    // run the conversion
    shell_exec($preparedCommand);
 
    // redirect the browser to the new image - this is more reliable than fpassthru
    header("Location: http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['PHP_SELF']).'/'.$img);
    exit;
    ?>
 
by karoly sz on 2009-07-25, tagged cache  convert  image  imagemagick  resize  thumbnail 

How to create a cacheable xml-rpc request

Recently I needed to use the xml-rpc lib with symfony. I created a function to make cache of xml-rpc requests using the symfony's sfFileCache and it work good.

I'm using the xml-rpc library http://phpxmlrpc.sourceforge.net/

public function callCache( $methodName, $params ){
 
  // generated a key to cache file
  $key = $methodName."_".implode('_', $params->getval() );
 
 
  $cache = new sfFileCache( array( 'cache_dir' => sfConfig::get('sf_cache_dir')."/xmlrpc/" ) );
 
  // check if already exist the cache file 
 
  if( ! $cache->has( $key ) ){
 
    //init xml-rpc message/
 
    $f = new xmlrpcmsg($methodName, $params);
 
    $f->addParam($params);
 
    $c = new xmlrpc_client("/xml-rpc", $this->host, 443, 'https' );
 
    $c->setCredentials($this->username, $this->password);
 
    $c->setDebug( $this->debug );
 
 
    $response = $c->send($f);
 
 
    $cache->set( $key , serialize( $response ), 3600);
 
 
  }else{
 
 
    $response = $cache->get( $key );
 
    $response = unserialize( $response );
 
 
  }
 
 
  if( ! $response->value() ){
 
    $this->erro( $response->errno, $response->faultString() );
 
  }
 
 
  $results = php_xmlrpc_decode( $response->value() );
 
 
  $this->rows = count($results);
 
 
  $this->data = $results;
 
}
 
by nei santos on 2009-07-02, tagged cache  xmlrpc 

clear the cache without symfony command line interface

Some PHP code to clean the cache very useful when you don't have access to symfony "command line interface" on production server.

file: symfony_cc.php

<?php
function deltree($f)
{
  $sf = realpath($sf);
 
  if (is_dir($f)) {
    foreach(glob($f.'/*') as $sf) {
      if (is_dir($sf) && !is_link($sf)) {
        deltree($sf);
        if (is_writable($sf)) {
          echo 'Delete dir.: '.$sf."\n";
          rmdir($sf);
        }
      } else {
        if (is_writable($sf)) {
          echo 'Delete file: '.$sf."\n";
          unlink($sf);
        }
      }
    }
  } else {
    die('Error: '.$f.' not a directory');
  }
}
 
echo '<pre>';
echo 'Clean symfony cache'."\n";
echo "\n";
deltree('../../cache');
echo '</pre>';
 
by Olivier LOYNET on 2008-03-11, tagged cache  cli 
(1 comment)

get cached Thumbnail helper

This helper return path to a generate (and cached) thumbnail for an image and sizes given.

First it checks if the thumbnail as ever been created for the given size. If not, it created it and return the path to the thumbnail. Else, it will only return the path to the thumbnail.

Thumbnails are stored in a sub-directory of the original image named like [width]x[height].

examples : product/foobar.jpg which is 640x480 images - getThumbnail (320x320) will the first time generate the thumbnail "product/320x320/foobar.jpg", and return the path to this image.

parameters : - $image_path should be the path and filename of the image under uploads directory. ex: product/foobar.jpg - $width is the maximal thumbnail width - $height is the maximal thumbnail height

function getThumbnail($image,$width=null,$height=null, $scale = true, $inflate = true, $quality = 75)
{
    $image_dir=dirname($image);
    $image_file=basename($image);
    $thumbnail_dir='';
    if ($width>0) $thumbnail_dir.=$width;
    if ($height>0) $thumbnail_dir.='x'.$height;
    if ($width>0 || $height>0) $thumbnail_dir.='/';
    if (!file_exists(sfConfig::get('sf_upload_dir').'/'.$image_dir.'/'.$thumbnail_dir.$image_file) && ($width!=null || $height!=null))
    {
      if (!is_dir(sfConfig::get('sf_upload_dir').'/'.$image_dir.'/'.$thumbnail_dir))
      {
        mkdir (sfConfig::get('sf_upload_dir').'/'.$image_dir.'/'.$thumbnail_dir,0777);
      }
 
      $thumbnail = new sfThumbnail($width, $height,$scale,$inflate,$quality); 
      $thumbnail->loadFile(sfConfig::get('sf_upload_dir').'/'.$image_dir.'/'.$image_file);
      $thumbnail->save(sfConfig::get('sf_upload_dir').'/'.$image_dir.'/'.$thumbnail_dir.$image_file);
    }
    return '/uploads'.'/'.$image_dir.'/'.$thumbnail_dir.$image_file;
}
 

This is very usefull to use it in model like this :

In model :

  public function getThumbnail($width=null,$height=null)
  {
    sfLoader::loadHelpers('Thumbnail');
    return getThumbnail('product/'.$this->getImage(),$width,$height);
  }
 

in template :

<?php foreach ($products as $product) { ?>
<li><?php echo image_tag($product->getThumbnail(150,100)); ?></li>
<?php } ?>
 

limitation : - work on images of upload directories only (other dir might have permission problem) - the check of thumbnail existance don't take care of scale and inflate values. It is easy to update the code to stored thumbnail in different subdirectory according to these parameters.

by Sylvain PAPET on 2007-09-23, tagged cache  helper  thumbnail 
(1 comment)

Redirect cache output depending on module/action

In my current application I found that I often needed to perform a clear-cache to get newly published changes to work on the production site, but in doing this I would clear a lot of valuable data from the template cache.

One solution would have been to turn off cacheing in the appropriate cache.yml file, and then to implement it manually, which would have been fairly easy. However I really like the transparent cacheing feature of symfony, so wrote this extension to sfFileCache to redirect cache output to a safe place, providing that certain criteria are met.

Feedback welcome here.

/**
 * Class to modify location of cache dynamically, thus protecting important files against clear-cache
 *
 * @version 19 Feb 2007
 * 
 * Notes: to configure, place this class in the appropriate lib folder, then in the app settings,
 * enter the following under the all category:
 *
 * all:
 *   safe_cache:
 *     folder:                       altcache
 *     activate:                     [[module1, action1], [module2, action2] ...]
 *
 * Where "altcache" is the name of the alternative cache location, relative to the project root,
 * and the module/action pairs are the actions that the safe cache is to be switched on for.
 *
 * Finally this class needs to be installed in factories.yml:
 *
 * all:
 *   view_cache:
 *     class: SafeFileCache
 *
 * Note that intercepting the constructor was not particularly feasible, as it is called very
 * early in the bootstrapping process, before the context instance is available. This means that
 * getModuleName and getActionName are not be available to test against, leaving us to test the
 * URL, which not be as clean.
 */
class SafeFileCache extends sfFileCache
{
  public function get($id, $namespace = self::DEFAULT_NAMESPACE, $doNotTestCacheValidity = false)
  {
    $isDiff = $this->isDifferentCache();
    if ($isDiff)
    {
      $save = $this->cacheDir;
      $this->cacheDir = $this->getCachePath();
    }
 
    $result = parent::get($id, $namespace, $doNotTestCacheValidity);
 
    if ($isDiff)
    {
      $this->cacheDir = $save;
    }
 
    return $result;
  }
 
  public function has($id, $namespace = self::DEFAULT_NAMESPACE, $doNotTestCacheValidity = false)
  {
    $isDiff = $this->isDifferentCache();
    if ($isDiff)
    {
      $save = $this->cacheDir;
      $this->cacheDir = $this->getCachePath();
    }
 
    $result = parent::has($id, $namespace, $doNotTestCacheValidity);
 
    if ($isDiff)
    {
      $this->cacheDir = $save;
    }
 
    return $result;
  }
 
  public function set($id, $namespace = self::DEFAULT_NAMESPACE, $data)
  {
    $isDiff = $this->isDifferentCache();
    if ($isDiff)
    {
      $save = $this->cacheDir;
      $this->cacheDir = $this->getCachePath();
    }
 
    $result = parent::set($id, $namespace, $data);
 
    if ($isDiff)
    {
      $this->cacheDir = $save;
    }
 
    return $result;
  }
 
  public function remove($id, $namespace = self::DEFAULT_NAMESPACE)
  {
    $isDiff = $this->isDifferentCache();
    if ($isDiff)
    {
      $save = $this->cacheDir;
      $this->cacheDir = $this->getCachePath();
    }
 
    $result = parent::remove($id, $namespace);
 
    if ($isDiff)
    {
      $this->cacheDir = $save;
    }
 
    return $result;
  }
 
  private function isDifferentCache()
  {
    $context = sfContext::getInstance();
    $strModule = $context->getModuleName();
    $strAction = $context->getActionName();
 
    $run = false;
    $allowed = sfConfig::get('app_safe_cache_activate');
    if (is_array($allowed))
    {
      foreach($allowed as $allow)
      {
        if (is_array($allow) && (count($allow) == 2))
        {
          list($mod, $act) = $allow;
          if (($mod == $strModule) && ($act == $strAction))
          {
            $run = true;
            break;
          }
        }
      }
    }
 
    return ($run);
  }
 
  private function getCachePath()
  {
    $sysDir = sfConfig::get('sf_root_dir');
    $oldDir = $sysDir . DIRECTORY_SEPARATOR . sfConfig::get('sf_cache_dir_name');
    $newDir = $sysDir . DIRECTORY_SEPARATOR . sfConfig::get('app_safe_cache_folder');
    $cacheDir = $newDir . str_replace($oldDir, '', $this->cacheDir);
 
    return $cacheDir;
  }
}
by halfer on 2007-02-19, tagged cache  clear  filecache  folder 

cache objects

This is a simple example for object cache.

$key = md5('myPropelObjectKey');
$sfProcessCache = new sfProcessCache();
if ($sfProcessCache->has($key)) {
  $obj = unserialize($sfProcessCache->get($key));
}else{
  $obj = Table::doSelect();
  $sfProcessCache->set($key, serialize($obj))
}
by Gordon Franke on 2006-10-30, tagged cache  database 

function/method cache

My alternative for sfFunctionCache, which can work with objects/classes. Useful for caching external data, like rss feeds etc.

class myFunctionCache extends sfFileCache
{
  public function __construct($dir=null)
  {
    if (is_null($dir)) $dir = SF_ROOT_DIR.'/cache/'.SF_APP.'/function';
    parent::__construct($dir);
  }
  public function call ()
  {
    $arguments = func_get_args();
 
    // check if first argument is array (object/class function call)
    if (is_array($arguments[0])) $id = md5(serialize(array_merge(array(0=>$arguments[0][1], 1=>(is_object($arguments[0][0]) ? get_class($arguments[0][0]) : $arguments[0][0]), array_slice($arguments_serialize=$arguments, 1)))));
    else $id = md5(serialize($arguments));
 
    $data = $this->get($id);
    if ($data !== null)
    {
      $array = unserialize($data);
      $output = $array['output'];
      $result = $array['result'];
    }
    else
    {
      $target = array_shift($arguments);
      ob_start();
      ob_implicit_flush(false);
      $result = call_user_func_array($target, $arguments);
      $output = ob_get_clean();
      $this->set($id, '', serialize(array('output'=>$output, 'result'=>$result)));
    }
 
    if (!empty($output)) echo($output);
    return $result;
  }        
}

In action:

$cache = new myFunctionCache();
$rss_items = $cache->call(array(&$rss, 'getItems'), 'http://www.symfony-project.com/weblog/rss');
by Štěpán Ulver on 2006-10-03, tagged cache 
(1 comment)

Clearing the cache of another application

This is a bit of a hack, but at least it makes it possible to clear the cache across applications

sfToolkit::clearDirectory(
  sfConfig::get('sf_root_dir').'/cache/'.$app_name.'/templates/path/to/page/in/cache'
);

It is not using an internal URI, of course, since for now an application cannot know another application's routing rules.

If you don't include any path to a page in cache, the whole template cache is cleared.

by Francois Zaninotto on 2006-09-29, tagged cache