PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Mon Sep 28, 2020 1:54 pm

All times are UTC - 5 hours




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: Basic Page Cache
PostPosted: Wed Aug 23, 2006 7:42 pm 
Offline
Breakbeat Nuttzer
User avatar

Joined: Wed Mar 24, 2004 8:57 am
Posts: 13098
Location: Melbourne, Australia
This is just a bi-product of something I used to practise TDD with.

Syntax: [ Download ] [ Hide ]
<?php



/**

 * A very basic web page caching system

 * Stores pages in a cache, checks expiry times

 * and dumps the cache contents back.

 * @author Chris Corbyn

 * @license Lesser GNU Public License

 */


class PageCache

{

        /**

         * The directory where the cache resides

         * @var string path

         */


        protected $cacheDirectory = '/tmp';

        /**

         * The name of the current page as specified by the developer

         * @var string page name

         */


        protected $page;

        /**

         * Open file handle

         * @var resource file

         */


        protected $handle;

        /**

         * The cache timeout in seconds

         * @var int timeout

         */


        protected $timeout;

       

        /**

         * Constructor

         * @param string page name

         */


        public function __construct($pagename)

        {

                $this->page = $pagename;

        }

        /**

         * Specify a maximum age in seconds for cached pages

         * @param int seconds

         */


        public function setTimeout($seconds)

        {

                $this->timeout = (int) $seconds;

        }

        /**

         * Set the directory to use to cache pages

         * @var string path

         */


        public function setCacheDirectory($path)

        {

                $this->cacheDirectory = $path;

        }

        /**

         * Check if the cache is writable

         * @return boolean

         */


        public function isWritable()

        {

                return is_writable($this->cacheDirectory);

        }

        /**

         * Start output buffering to catch the page contents

         * Open the file ready for writing

         */


        public function startCaching()

        {

                if ($this->isWritable())

                {

                        ob_start();

                        $this->handle = fopen($this->getCachedFilePath(), 'w+');

                }

        }

        /**

         * Commit the contents of the buffer to the cache

         */


        public function write()

        {

                if ($this->handle)

                {

                        $buffer = ob_get_clean();

                        fwrite($this->handle, $buffer);

                }

        }

        /**

         * Check if the page we have open is already cached

         * @return boolean

         */


        public function isCached()

        {

                return file_exists($this->getCachedFilePath());

        }

        /**

         * Get the contents of the already cached page

         * @return string page data

         */


        public function getContents()

        {

                if ($this->isCached())

                {

                        return file_get_contents($this->getCachedFilePath());

                }

        }

        /**

         * Print the contents of the cached page to the screen

         */


        public function dump()

        {

                echo $this->getContents();

        }

        /**

         * Get the path the file which we're working with

         * @access private

         * @return string path

         */


        private function getCachedFilePath()

        {

                return $this->cacheDirectory.'/'.$this->page;

        }

        /**

         * Get the age in seconds of the already cached file

         * @return int age

         */


        public function getAge()

        {

                if ($this->isCached())

                {

                        return time() - filemtime($this->getCachedFilePath());

                }

                else return 0;

        }

        /**

         * Check if the currently cached file is out of date

         * @return boolean

         */


        public function isExpired()

        {

                return ($this->timeout <= $this->getAge());

        }

        /**

         * Remove old cache data for this page

         */


        public function cleanUp()

        {

                if ($this->isCached() && $this->isWritable())

                {

                        unlink($this->getCachedFilePath());

                }

        }

}



?>


And the tests that drove the code (for anyone who cares :P)....

Syntax: [ Download ] [ Hide ]
Mock::GeneratePartial('PageCache', 'PartialPageCache', array('getAge'));



class TestOfPageCache extends UnitTestCase

{

        public function testCacheIsWritable()

        {

                $cache = new PageCache('mypage');

                $cache->setCacheDirectory('./cache');

                $this->assertTrue($cache->isWritable());

                @fopen('./cache/test.txt', 'w+');

                $this->assertTrue(file_exists('./cache/test.txt'));

                @unlink('./cache/test.txt');

                $this->assertFalse(file_exists('./cache/test.txt'));

        }

       

        public function testPageCacheFileIsCreated()

        {

                $cache = new PageCache('mypage');

                $cache->setCacheDirectory('./cache');

                $this->assertTrue($cache->isWritable());

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

                @unlink('./cache/mypage');

                $this->assertFalse(file_exists('./cache/mypage'));

        }

       

        public function testCacheContent()

        {

                $cache = new PageCache('mypage');

                $cache->setCacheDirectory('./cache');

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

               

                $test_output = "Some <strong>test</strong> output";

                echo $test_output;

               

                $cache->write();

               

                $this->assertEqual($test_output, $cache->getContents());

               

                @unlink('./cache/mypage');

                $this->assertFalse(file_exists('./cache/mypage'));

        }

       

        public function testCacheTimeout()

        {

                $cache = new PartialPageCache($this);

                $cache->__construct('mypage');

                $cache->setCacheDirectory('./cache');

                $cache->setTimeout(60 * 60); //1 hour in seconds

               

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

                $test_output = "Dummy";

                echo $test_output;

                $cache->write();

                $cache->setReturnValue('getAge', 60 * 60 + 10); //10 seconds expired

                $this->assertTrue($cache->isExpired());

                @unlink('./cache/mypage');

                $this->assertFalse(file_exists('./cache/mypage'));

                unset($cache);

               

                $cache = new PartialPageCache($this);

                $cache->__construct('mypage');

                $cache->setCacheDirectory('./cache');

                $cache->setTimeout(60 * 60); //1 hour in seconds

               

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

                $test_output = "Dummy";

                echo $test_output;

                $cache->write();

                $cache->setReturnValue('getAge', 60 * 60 - 10); //10 seconds remaining

                $this->assertFalse($cache->isExpired());

                @unlink('./cache/mypage');

                $this->assertFalse(file_exists('./cache/mypage'));

               

                $cache = new PageCache('mypage');

                $cache->setCacheDirectory('./cache');

                $cache->setTimeout(60 * 60); //1 hour in seconds

               

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

                $test_output = "Dummy";

                echo $test_output;

                $cache->write();

                $this->assertFalse($cache->isExpired());

                @unlink('./cache/mypage');

                $this->assertFalse(file_exists('./cache/mypage'));

        }

       

        public function testDumpOfCacheData()

        {

                $cache = new PageCache('mypage');

                $cache->setCacheDirectory('./cache');

                $cache->setTimeout(60 * 60); //1 hour in seconds

               

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

                $test_output = "Dummy";

                echo $test_output;

                $cache->write();

                $this->assertFalse($cache->isExpired());

               

                ob_start();

                if (!$cache->isExpired())

                {

                        $cache->dump();

                }

                $cache_data = ob_get_clean();

               

                $this->assertEqual($cache_data, $test_output);

               

                @unlink('./cache/mypage');

                $this->assertFalse(file_exists('./cache/mypage'));

        }

       

        public function testOfCleaning()

        {

                $cache = new PartialPageCache($this);

                $cache->__construct('mypage');

                $cache->setCacheDirectory('./cache');

                $cache->setTimeout(60 * 60); //1 hour in seconds

               

                $cache->startCaching();

                $this->assertTrue(file_exists('./cache/mypage'));

                $test_output = "Dummy";

                echo $test_output;

                $cache->write();

                $cache->setReturnValue('getAge', 60 * 60 + 10); //10 seconds expired

                $this->assertTrue($cache->isExpired());

               

                if ($cache->isExpired())

                {

                        $cache->cleanUp();

                }

                $this->assertFalse(file_exists('./cache/mypage'));

        }

}


A basic example (maybe in a controller):

Syntax: [ Download ] [ Hide ]
$cache = new PageCache($this->page);

$cache->setTimeout($this->cacheTimeout);

if ($cache->isCached() && !$cache->isExpired())

{

    $cache->dump();

}

else

{

    $cache->startCaching();

   

    $this->pseudoSendYourPageOutput();

   

    $cache->write();

}


I guess you could use if it's not feasible to call write() manually.

(Ok, I really need some sleep 8O )


Top
 Profile  
 
 Post subject:
PostPosted: Thu Aug 24, 2006 4:15 am 
Offline
DevNet Master
User avatar

Joined: Mon Sep 19, 2005 6:24 am
Posts: 3587
Location: London
For pure semantics, you could use the realpath() function on the setter for path; and a quick check that is does exist.

Syntax: [ Download ] [ Hide ]
/**

         * Set the directory to use to cache pages

         * @var string path

         * @return bool directory exists

         */


        public function setCacheDirectory($path)

        {

                if (!$path = realpath($path)) return false;



                $this->cacheDirectory = $path;

                return true;

        }


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group