Using __destruct() to cleanup a runtime caching class (disk)

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Using __destruct() to cleanup a runtime caching class (disk)

Post by Chris Corbyn »

I'm trying to use __destruct() to clean temporary files back off the disk at the end of script execution. I've written a basic runtime cache layer, then I have MemCache (faster) and DiskCache (far less memory). DiskCache writes files to disk. These are only supposed to exist for the duration of that script execution, thus, when the cache object is destroyed (at end of execution???) they should get deleted. __destruct() only appears to be running for one instance of the cache, all other instances are leaving files on the disk because __destruct() is not being called. Am I misunderstanding when __destruct() will run?

Code: Select all

<?php

/**
 * Swift Mailer disk runtime cache
 * Please read the LICENSE file
 * @author Chris Corbyn <chris@w3style.co.uk>
 * @package Swift_Cache
 * @license GNU Lesser General Public License
 */

require_once dirname(__FILE__) . "/../ClassLoader.php";
Swift_ClassLoader::load("Swift_Cache");

/**
 * Caches data in files on disk - this is the best approach if possible
 * @package Swift_Cache
 * @author Chris Corbyn <chris@w3style.co.uk>
 */
class Swift_Cache_Disk extends Swift_Cache
{
	/**
	 * Open file handles
	 * @var array
	 */
	protected $open = array();
	/**
	 * The prefix to prepend to files
	 * @var string
	 */
	protected $prefix;
	/**
	 * The save path on disk
	 * @var string
	 */
	protected static $save_path = "/tmp";
	
	/**
	 * Ctor
	 */
	public function __construct()
	{
		$this->prefix = md5(uniqid(microtime(), true));
	}
	/**
	 * Set the save path of the disk - this is a global setting and called statically!
	 * @param string The path to a writable directory
	 */
	public static function setSavePath($path="/tmp")
	{
		self::$save_path = $path;
	}
	/**
	 * Write data to the cache
	 * @param string The cache key
	 * @param string The data to write
	 */
	public function write($key, $data)
	{
		$handle = fopen(self::$save_path . "/" . $this->prefix . $key, "ab");
		fwrite($handle, $data);
		fclose($handle);
	}
	/**
	 * Clear the cached data (unlink)
	 * @param string The cache key
	 */
	public function clear($key)
	{
		@unlink(self::$save_path . "/" . $this->prefix . $key);
	}
	/**
	 * Check if data is cached for $key
	 * @param string The cache key
	 * @return boolean
	 */
	public function has($key)
	{
		return file_exists(self::$save_path . "/" . $this->prefix . $key);
	}
	/**
	 * Read data from the cache for $key
	 * @param string The cache key
	 * @param int The number of bytes to read
	 * @return string
	 */
	public function read($key, $size=null)
	{
		if ($size === null) $size = 8190;
		if (!$this->has($key)) return false;
		
		if (!isset($this->open[$key]))
		{
			$this->open[$key] = fopen(self::$save_path . "/" . $this->prefix . $key, "rb");
		}
		if (feof($this->open[$key]))
		{
			fclose($this->open[$key]);
			unset($this->open[$key]);
			return false;
		}
		$ret = fread($this->open[$key], $size);
		if ($ret !== false)
		{
			return $ret;
		}
		else
		{
			fclose($this->open[$key]);
			unset($this->open[$key]);
			return false;
		}
	}
	/**
	 * Dtor.
	 * Clear out cached data at end of script execution or cache destruction
	 */
	public function __destruct()
	{
		foreach (glob(self::$save_path . "/" . $this->prefix . "*") as $f)
		{
			@unlink($f);
		}
	}
}
Can anyone think of a more relaible approach? For the PHP4 version of the code, I used register_shutdown_function(), but it *never* seems to run:

Code: Select all

/**
 * Caches data in files on disk - this is the best approach if possible
 * @package Swift_Cache
 * @author Chris Corbyn <chris@w3style.co.uk>
 */
class Swift_Cache_Disk extends Swift_Cache
{
	/**
	 * Open file handles
	 * @var array
	 */
	var $open = array();
	/**
	 * The prefix to prepend to files
	 * @var string
	 */
	var $prefix;
	
	/**
	 * Ctor
	 */
	function Swift_Cache_Disk()
	{
		$this->prefix = md5(uniqid(microtime(), true));
		register_shutdown_function(array($this, "__destruct"));
	}

// ... SNIP ....
Totally at a loss here :(
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post by Chris Corbyn »

Never mind :) Turns out working directories change during the shutdown of a PHP script. I needed to pass an absolute path, that's all :) FYI, the register_shutdown_function() trick works a peach in PHP4.
Post Reply