This example shows how to create and use a simple cache with
ezcCacheManager:
- <?php
-
- require_once 'tutorial_autoload.php';
-
- $options = array(
- 'ttl' => 30,
- );
-
- ezcCacheManager::createCache( 'simple', '/tmp/cache/plain', 'ezcCacheStorageFilePlain', $options );
-
- $myId = 'unique_id_1';
- $mySecondId = 'id_2';
-
- $cache = ezcCacheManager::getCache( 'simple' );
-
- if ( ( $dataOfFirstItem = $cache->restore( $myId ) ) === false )
- {
- $dataOfFirstItem = "Plain cache stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $myId, $dataOfFirstItem );
- }
-
- if ( ( $dataOfSecondItem = $cache->restore( $mySecondId ) ) === false )
- {
- $dataOfSecondItem = "Plain cache 2 stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $mySecondId, $dataOfSecondItem );
- }
-
- var_dump( $dataOfFirstItem, $dataOfSecondItem );
-
- ?>
Time-to-live is defined as 30 seconds in this case; if left
out, the cache will have a lifespan of 24 hours. On line 9, the cache
configuration is stored in the cache
manager. The created cache uses the cache identifier "simple" and will reside in the directory
/tmp/cache/plain. (Note: This directory must exist and must be writable!) To store a cache item, the storage
class ezcCacheStorageFilePlain will be used.
Line 11 defines a cache key for a cache item. The next line defines a
second unique cache key for a second cache item. After that (line 14), the
newly-created cache object is retrieved from ezcCacheManager. Lines 16 and
22 show how to check for cached data: ezcCacheStorage::restore()
will return bool false if no valid cache data is found for the given ID.
If no valid data is found, the data will be generated
and stored in the cache later (lines 17-18 and 24-25). The last line outputs the
data, so you can follow how it's cached for 30 seconds by running the
example multiple times in a short time frame. After 30 seconds, the cache data
will become invalid and will be regenerated.
Instead of calling the ezcCacheManager::getCache() method yourself it is also
possible to use delayed initialization. When using this it is not required to
configure all the caches first by calling the ezcCacheManager::createCache()
method. Instead it would allow you to configure/create caches on demand, this
is called lazy, or delayed initialization. You can find a description how you
can use it for your own components and how it works in the ezcBase
tutorial. The keyword for the cache component is
ezcInitConfigurationManager.
- <?php
-
- require_once 'tutorial_autoload.php';
-
- class customLazyCacheConfiguration implements ezcBaseConfigurationInitializer
- {
- public static function configureObject( $id )
- {
- $options = array( 'ttl' => 30 );
-
- switch ( $id )
- {
- case 'simple':
- ezcCacheManager::createCache( 'simple', '/tmp/cache/plain', 'ezcCacheStorageFilePlain', $options );
- break;
- }
- }
- }
-
- ezcBaseInit::setCallback(
- 'ezcInitCacheManager',
- 'customLazyCacheConfiguration'
- );
-
- $myId = 'unique_id_1';
- $mySecondId = 'id_2';
-
- $cache = ezcCacheManager::getCache( 'simple' );
-
- if ( ( $dataOfFirstItem = $cache->restore( $myId ) ) === false )
- {
- $dataOfFirstItem = "Plain cache stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $myId, $dataOfFirstItem );
- }
-
- if ( ( $dataOfSecondItem = $cache->restore( $mySecondId ) ) === false )
- {
- $dataOfSecondItem = "Plain cache 2 stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $mySecondId, $dataOfSecondItem );
- }
-
- var_dump( $dataOfFirstItem, $dataOfSecondItem );
-
- ?>
Differences with the previous example can be seen in lines 5 to 23. In lines 20
to 23 you tell the delayed initialization mechanism to use the
customLazyCacheConfiguration as lazy initialization provider for the
ezcInitConfigurationManager context. The customLazyCacheConfiguration class
implements the configureObject() method that will automatically be called when
ezcCacheManager::getCache() is called with a cache identifier that has not been
created yet through ezcCacheManager::createCache(), as you can see in line 14.
The following example shows how the cache manager deals with multiple caches:
- <?php
-
- require_once 'tutorial_autoload.php';
-
- $optionsPlain = array(
- 'ttl' => 30,
- );
- $optionsArray = array(
- 'ttl' => 45,
- );
-
- ezcCacheManager::createCache( 'plain', '/tmp/cache/plain', 'ezcCacheStorageFilePlain', $optionsPlain );
- ezcCacheManager::createCache( 'array', '/tmp/cache/array', 'ezcCacheStorageFileArray', $optionsArray );
-
- $myId = 'unique_id_2';
-
- $cache = ezcCacheManager::getCache( 'plain' );
-
- if ( ( $plainData = $cache->restore( $myId ) ) === false )
- {
- $plainData = "Plain cache stored on " . date( 'Y-m-d, H:m:s' );
- $cache->store( $myId, $plainData );
-
- sleep( 2 );
- }
-
- echo "Plain cache data:\n";
- var_dump( $plainData );
-
- $cache = ezcCacheManager::getCache( 'array' );
-
- if ( ( $arrayData = $cache->restore( $myId ) ) === false )
- {
- $arrayData = array(
- $plainData,
- "Array cache stored on " . date( 'Y-m-d, H:m:s'),
- true,
- 23
- );
- $cache->store( $myId, $arrayData );
- }
-
- echo "Array cache data:\n";
- var_dump( $arrayData );
-
- ?>
In lines 12 and 13, two caches are created. Each cache must
reside in its own location and must have a different cache identifier. We
use two different options for the lifetime of the caches to show how they act
independently.
Since the first cache reuses the location already used in example 1,
we use a different cache key here.
Lines 15 to 25 are almost identical to the code from example 1,
except that the program will pause for two seconds when generating
the plain cache, in order to show different generation times for the two
caches.
On line 30, the second cache object is retrieved, which is capable of storing
arrays. Therefore, we store the data from the plain cache here and
generate some additional data to be stored in an array. Running this
example multiple times will give you different results
since the second cache has a longer lifetime and will therefore hold its data
longer than the first one.
As the next example shows, the ezcCacheStorage class is capable of more advanced
features. This example uses extra attributes in addition to the cache key:
- <?php
-
- require_once 'tutorial_autoload.php';
-
- $options = array(
- 'ttl' => 30,
- );
-
- ezcCacheManager::createCache( 'array', '/tmp/cache/array', 'ezcCacheStorageFileArray', $options );
-
- $exampleData = array(
- 'unique_id_3_a' => array( 'language' => 'en', 'section' => 'articles' ),
- 'unique_id_3_b' => array( 'language' => 'de', 'section' => 'articles' ),
- 'unique_id_3_c' => array( 'language' => 'no', 'section' => 'articles' ),
- 'unique_id_3_d' => array( 'language' => 'de', 'section' => 'tutorials' ),
- );
-
- $cache = ezcCacheManager::getCache( 'array' );
-
- foreach ( $exampleData as $myId => $exampleDataArr )
- {
- if ( ( $data = $cache->restore( $myId, $exampleDataArr ) ) === false )
- {
- $cache->store( $myId, $exampleDataArr, $exampleDataArr );
- }
- }
-
- echo "Data items with attribute <section> set to <articles>: " .
- $cache->countDataItems( null, array( 'section' => 'articles' ) ) .
- "\n";
-
- echo "Data items with attribute <language> set to <de>: " .
- $cache->countDataItems( null, array( 'language' => 'de' ) ) .
- "\n\n";
-
- $cache->delete( null, array( 'language' => 'de' ) );
-
- echo "Data items with attribute <section> set to <articles>: " .
- $cache->countDataItems( null, array( 'section' => 'articles' ) ) .
- "\n";
-
- echo "Data items with attribute <language> set to <de>: " .
- $cache->countDataItems( null, array( 'language' => 'de' ) ) .
- "\n\n";
-
- ?>
After the creation of an array cache, some sample data is created (lines
11-16). Data is identified by cache key s, which are associated with
arrays. Each array will be used to store the content and the attributes
together. Attribute s describe a cache item s in further detail.
In line 20, a foreach loop starts, which stores all example data in the cache.
After that, the method ezcCacheStorageFile::countDataItems() is used to count
cache items that meet certain criteria. The first parameter here would be a
cache key.
When this is set, the method should always return 1 or 0, because only one cache
item per cache key may exist. In this example, the cache items with the specified attribute are
counted. The attributes to match are supplied as the second parameter. The
first method call will return 3 (line 28), since we have three cache items that
have the attribute "section" set to "articles". The second call (line 32)
should return 2, because two data items have the attribute "language" set to the
value "de".
On line 36 the storage object is told to delete all cache items that have
the attribute "language" set to "de". Therefore, the next calls to
ezcCacheStorageFile::countDataItems() will return 2 and 0.
If either of Memcache or APC PHP extensions is installed, then the caching
performance can be improved considerably by storing the cache data in memory
between requests.
To use the APC cache storage, the APC PHP extension must be installed. The
corresponding storage class is ezcCacheStorageApcPlain. Note, that the other
existing APC storage class, ezcCacheStorageApcArray has been deprecated in
favor of hierarchical caching provided by ezcCacheStack. It is not recommended
to use this class further on, since it will be removed in the next major
version of the Cache component.
The following example shows how to create and use a plain APC storage. It is
the same as the simple example above, but using the ezcCacheStorageApcPlain
class instead of ezcCacheStorageFilePlain. The second parameter of the
createCache() method is arbitrary, because an existing path is not needed.
However, the $location ensures the uniqueness of a cache storage in the
manager. Therefore this parameter should be used accordingly.
- <?php
-
- require_once 'tutorial_autoload.php';
-
- $options = array(
- 'ttl' => 30,
- );
-
- ezcCacheManager::createCache( 'apc', 'apc', 'ezcCacheStorageApcPlain', $options );
-
- $myId = 'unique_id_1';
- $mySecondId = 'id_2';
-
- $cache = ezcCacheManager::getCache( 'apc' );
-
- if ( ( $dataOfFirstItem = $cache->restore( $myId ) ) === false )
- {
- $dataOfFirstItem = "Plain cache stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $myId, $dataOfFirstItem );
- }
-
- if ( ( $dataOfSecondItem = $cache->restore( $mySecondId ) ) === false )
- {
- $dataOfSecondItem = "Plain cache 2 stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $mySecondId, $dataOfSecondItem );
- }
-
- var_dump( $dataOfFirstItem, $dataOfSecondItem );
-
- ?>
Certain options must be set before creating a Memcache cache storage. Changing
these options after the storage has been created does not affect the object in
any way, since the connection to the Memcache is established in the
constructor.
- host
- The name of the host running Memcache. The default is 'localhost'.
- port
- The port on which to connect to the Memcache host. The default is 11211.
- persistent
- Determines if the connection to the Memcache server should be persistent. A
persistent connection does not close when the script ends. By default this is
false.
- compressed
- If the data is to be compressed in the cache. The zlib extension is required,
if this option is set to true. False is the default.
The following example shows how to create and use a plain Memcache storage. It
is the same as the simple example above, but using the
ezcCacheStorageMemcachePlain class instead of ezcCacheStorageFilePlain. The
second parameter of the createCache() method is chosen arbitrary, because an
existing path is not needed. However, the $location parameter takes care for
the uniqueness of the storage in the manager. The $host an $port options just
reflect the defaul here, they could also have been left out.
- <?php
-
- require_once 'tutorial_autoload.php';
-
- $options = array(
- 'ttl' => 30,
- 'host' => 'localhost',
- 'port' => 11211
- );
-
- ezcCacheManager::createCache( 'memcache', 'memcache', 'ezcCacheStorageMemcachePlain', $options );
-
- $myId = 'unique_id_1';
- $mySecondId = 'id_2';
-
- $cache = ezcCacheManager::getCache( 'memcache' );
-
- if ( ( $dataOfFirstItem = $cache->restore( $myId ) ) === false )
- {
- $dataOfFirstItem = "Plain cache stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $myId, $dataOfFirstItem );
- }
-
- if ( ( $dataOfSecondItem = $cache->restore( $mySecondId ) ) === false )
- {
- $dataOfSecondItem = "Plain cache 2 stored on " . date( 'Y-m-d, H:i:s' );
- $cache->store( $mySecondId, $dataOfSecondItem );
- }
-
- var_dump( $dataOfFirstItem, $dataOfSecondItem );
-
- ?>
The ezcCacheStack class allows you to build a stack of arbitrary cache storages
that implement ezcCacheStackable storage. This stack allows you to combine very
fast caches (like APC and Memcache), which are mostly small, with slower ones,
that are usually quite large. Similar techniques are used in CPU caches and
file system caches.
Whenever data is stored in a cache stack, it is stored in all of the stacked
storages. For each of the storages, an $itemLimit is configured that determines
how many items may reside in a cache. If this limit is reached for a storage
during the store operation of a new item, a certain amount of items is removed
from that storage to free up space. The fraction of $itemLimit that is freed
when reaching the limit is the $freeRate of the storage.
The following example shows how 2 caches are combined to a stack. Assume that
$storageApc contains an instance of ezcCacheStorageApcPlain and $storageFile
contains an instance of ezcCacheStorageFileArray.
- <?php
-
- require_once 'tutorial_autoload.php';
-
- $stack = new ezcCacheStack( 'stack' );
-
- $stack->pushStorage(
- new ezcCacheStackStorageConfiguration(
- 'file',
- $fileStorage,
- 1000000,
- .5
- )
- );
- $stack->pushStorage(
- new ezcCacheStackStorageConfiguration(
- 'apc',
- $apcStorage,
- 1000,
- .3
- )
- );
-
- $stack->options->replacementStrategy = 'ezcCacheStackLfuReplacementStrategy';
-
- // ... somewhere else...
-
- $stack->store(
- 'id_1', 'id_1_data'
- );
- $stack->store(
- 'id_2', 'id_2_data', array( 'attribute' => 'value' )
- );
- $id1data = $stack->restore( 'id_1' );
-
- ?>
The ezcCacheStack class (which is itself a descendant of ezcCacheStorage) is
initialized with an arbitrary location string. This string is actually not
used, since a stack does not need a dedicated location. However, the
ezcCacheManager needs this identifier for sanity checks, so it should be a
sensible key.
The method ezcCacheStack->push() adds a new ezcCacheStackableStorage to the
stack. Therefore, the $fileStorage is resides on the very bottom of the stack
and the APC storage is at the top. All implementations of ezcCacheStorage
inside the Cache component also implement ezcCacheStackableStoragel, so you can
stack all of them. To ease the internal handling of the storage configurations,
the ezcCacheStackStorageConfiguration class is used. In addition, objects of
this type perform sanity checks on their parameters.
The first parameter to the constructor of a storage configuration is an
identifier which identifies the storage uniquely inside a stack. If you make
consequent use of ezcCacheManager and the $location parameter of each storage,
you should use the ezcCacheStorage->$location here, since it is already unique
over all storages. Remember, that you never change the identifier of the
storage in the stack between requests, without calling ezcCacheStack->reset().
This will considerably harm your stored data and produce unpredictable
behavior of the stack.
The third parameter to ezcCacheStackStorageConfiguration->__construct() is the
item limit for that storage. In this sense, $fileStorage may contain up to a
million items, while $apcStorage may only contain 1,000. The last parameter
is the $freeRate assigned to the storage. If the $fileStorage reaches 1,000,000
items, 500,000 of them will be freed. For the APC storage, only 300 items will
be removed when the item limit is reached.
For the freeing of items, the cache stack first purges all outdated items from
the affected storage using ezcCacheStackableStorage->purge(). If this does not
remove the desired number of items, a special replacement strategy is utilized
to free up more items. In the example above, the replacement strategy
ezcCacheStackLfuReplacementStrategy (LRU = Least Frequently Used) is chosen.
This strategy will record every access (store/restore) to a cache item and will
purge those first, which have been least frequently accessed. The default
replacement strategy is ezcCacheStackLruReplacementStrategy (LRU = Least
Recently Used), which removes such items first, that have been accessed least
recently.
Usually, the faster caches will run full first in will therefore be purged
first. The result is, that these caches contain the "most important" (depending
on the replacement strategy) items. Items which are not used that much will be
purged from fast caches soon and will only be stored in the slower caches. The
stack will always restore an item from the storage in which it is found first.
As you have seen in the above example, storing and restoring with caches works
exactly like with other cache storages.
The ezcCacheManager is used to lazy initialize cache objects when they are first
needed in your application and to make caches globally available. On a first
glance this does not work with ezcCacheStack, since ready to use
ezcCacheStackableStorages are needed for its configuration. To allow lazy
initialization, a class that implements ezcCacheStackConfigurator can be used.
- <?php
-
- require_once 'tutorial_autoload.php';
-
- class myCustomConfigurator extends ezcCacheStackConfigurator
- {
- public static function configure( ezcCacheStack $stack )
- {
- // ... create your storages here or fetch from manager...
- $stack->pushStorage(
- new ezcCacheStackStorageConfiguration(
- 'file',
- $fileStorage,
- 1000000,
- .5
- )
- );
- $stack->pushStorage(
- new ezcCacheStackStorageConfiguration(
- 'apc',
- $apcStorage,
- 1000,
- .3
- )
- );
- }
- }
-
- $stackOptions = array(
- 'bubbleUpOnRestore' => true,
- 'configurator' => 'myCustomConfigurator',
- );
-
- $stack = new ezcCacheStack( 'stack' );
- ezcCacheManager::createCache(
- 'stack',
- 'stack',
- 'ezcCacheStack',
- $stackOptions
- );
-
- // ... somewhere else...
-
- $stack = ezcCacheManager::getCache( 'stack' );
-
- ?>
This example configures a similar stack than the previous one. Instead of doing
so directly, a new class myCustomConfigurator is created which extends
ezcCacheStackConfigurator. The static configure() method is defined by this
interface and creates the storages (or receives them from the manager) to add
them to the given stack.
The class is configured to be used as the $configurator through the options
array that is given to ezcCacheManager->createCache(). The speciality about
this option is, that it is only used once: During the actual construction of
the stack, when it is first requested from the manager. In this case,
ezcCacheStack::__construct() calls myCustomConfigurator::configure() and
submits the fresh created stack instance to it.
Another option is shown in this example: $bubbleUpOnRestore. If this option
is set, every item that is restored from a lower level storage will be stored
in the caches above it again. While this sounds sensible at a first glance, it
has some fundamental draw backs:
- The "bubble up" process might again result in other items being purged from
upper storages. This can make restoring much slower.
- The restored item is only stored with the attributes assigned which have been
used for restoring it. If more attributes were assigned to that item, these
are lost in the upper storages.
- The time to live (TTL) of the item will be re-newed for the upper storages.