mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
Merge pull request #2677 from chillu/pulls/zend-aggregate
Skip tags in Zend_Cache for Aggregate if not available, better docs
This commit is contained in:
commit
16fe87e4aa
103
cache/Cache.php
vendored
103
cache/Cache.php
vendored
@ -1,109 +1,10 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SS_Cache provides a bunch of static functions wrapping the Zend_Cache system
|
||||
* The `[api:SS_Cache]` class provides a bunch of static functions wrapping the Zend_Cache system
|
||||
* in something a little more easy to use with the SilverStripe config system.
|
||||
*
|
||||
* A Zend_Cache has both a frontend (determines how to get the value to cache,
|
||||
* and how to serialize it for storage) and a backend (handles the actual
|
||||
* storage).
|
||||
*
|
||||
* Rather than require library code to specify the backend directly, cache
|
||||
* consumers provide a name for the cache backend they want. The end developer
|
||||
* can then specify which backend to use for each name in their project's
|
||||
* _config.php. They can also use 'all' to provide a backend for all named
|
||||
* caches.
|
||||
*
|
||||
* End developers provide a set of named backends, then pick the specific
|
||||
* backend for each named cache. There is a default File cache set up as the
|
||||
* 'default' named backend, which is assigned to 'all' named caches.
|
||||
*
|
||||
* <h2>Using a cache</h2>
|
||||
*
|
||||
* <code>
|
||||
* // foo is any name (try to be specific), and is used to get configuration
|
||||
* // & storage info
|
||||
* $cache = SS_Cache::factory('foo');
|
||||
*
|
||||
* if (!($result = $cache->load($cachekey))) {
|
||||
* $result = caluate some how;
|
||||
* $cache->save($result);
|
||||
* }
|
||||
*
|
||||
* return $result;
|
||||
* </code>
|
||||
*
|
||||
* Normally there's no need to remove things from the cache - the cache
|
||||
* backends clear out entries based on age & maximum allocated storage. If you
|
||||
* include the version of the object in the cache key, even object changes
|
||||
* don't need any invalidation.
|
||||
*
|
||||
* <h2>Disabling cache in dev mode</h2>
|
||||
*
|
||||
* <code>
|
||||
* // _config.php
|
||||
* if (Director::isDev()) {
|
||||
* SS_Cache::set_cache_lifetime('any', -1, 100);
|
||||
* //
|
||||
* </code>
|
||||
*
|
||||
* <h2>Using memcached as a store</h2>
|
||||
*
|
||||
* <code>
|
||||
* // _config.php
|
||||
* SS_Cache::add_backend(
|
||||
* 'primary_memcached',
|
||||
* 'Memcached',
|
||||
* array(
|
||||
* 'host' => 'localhost',
|
||||
* 'port' => 11211,
|
||||
* 'persistent' => true,
|
||||
* 'weight' => 1,
|
||||
* 'timeout' => 5,
|
||||
* 'retry_interval' => 15,
|
||||
* 'status' => true,
|
||||
* 'failure_callback' => ''
|
||||
* )
|
||||
* );
|
||||
*
|
||||
* SS_Cache::pick_backend('primary_memcached', 'any', 10);
|
||||
*
|
||||
* // Aggregate needs a backend with tag support, which memcached doesn't
|
||||
* // provide
|
||||
* SS_Cache::pick_backend('default', 'aggregate', 20);
|
||||
* </code>
|
||||
*
|
||||
* <h2>Using APC as a store</h2>
|
||||
*
|
||||
* <code>
|
||||
* SS_Cache::add_backend('two-level', 'Two-Levels', array(
|
||||
* 'slow_backend' => 'File',
|
||||
* 'fast_backend' => 'Apc',
|
||||
* 'slow_backend_options' => array(
|
||||
* 'cache_dir' => TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache'
|
||||
* )
|
||||
* ));
|
||||
*
|
||||
* // No need for special backend for aggregate - TwoLevels with a File slow
|
||||
* // backend supports tags
|
||||
* SS_Cache::pick_backend('two-level', 'Two-Levels', 10);
|
||||
* </code>
|
||||
*
|
||||
* <h2>Invalidate an element</h2>
|
||||
*
|
||||
* <code>
|
||||
* $cache = SS_Cache::factory('foo');
|
||||
* $cache->remove($cachekey);
|
||||
* </code>
|
||||
*
|
||||
* <h2>Clear the cache</h2>
|
||||
*
|
||||
* This clears the entire backend, not just this named cache partition.
|
||||
*
|
||||
* <code>
|
||||
* $cache = SS_Cache::factory('foo');
|
||||
* $cache->clean(Zend_Cache::CLEANING_MODE_ALL);
|
||||
* </code>
|
||||
* @see http://doc.silverstripe.org/framework/en/topics/caching
|
||||
*
|
||||
* @package framework
|
||||
* @subpackage core
|
||||
|
@ -21,6 +21,127 @@ executing the action is limited to the following cases when performed via a web
|
||||
* A user is logged in with ADMIN permissions
|
||||
* An error occurs during startup
|
||||
|
||||
## Custom Caches
|
||||
## The Cache API
|
||||
|
||||
See `[api:SS_Cache]`.
|
||||
The `[api:SS_Cache]` class provides a bunch of static functions wrapping the Zend_Cache system
|
||||
in something a little more easy to use with the SilverStripe config system.
|
||||
|
||||
A `Zend_Cache` has both a frontend (determines how to get the value to cache,
|
||||
and how to serialize it for storage) and a backend (handles the actual
|
||||
storage).
|
||||
|
||||
Rather than require library code to specify the backend directly, cache
|
||||
consumers provide a name for the cache backend they want. The end developer
|
||||
can then specify which backend to use for each name in their project's
|
||||
configuration. They can also use 'all' to provide a backend for all named
|
||||
caches.
|
||||
|
||||
End developers provide a set of named backends, then pick the specific
|
||||
backend for each named cache. There is a default File cache set up as the
|
||||
'default' named backend, which is assigned to 'all' named caches.
|
||||
|
||||
## Using Caches
|
||||
|
||||
Caches can be created and retrieved through the `SS_Cache::factory()` method.
|
||||
The returned object is of type `Zend_Cache`.
|
||||
|
||||
:::php
|
||||
// foo is any name (try to be specific), and is used to get configuration
|
||||
// & storage info
|
||||
$cache = SS_Cache::factory('foo');
|
||||
if (!($result = $cache->load($cachekey))) {
|
||||
$result = caluate some how;
|
||||
$cache->save($result);
|
||||
}
|
||||
return $result;
|
||||
|
||||
Normally there's no need to remove things from the cache - the cache
|
||||
backends clear out entries based on age and maximum allocated storage. If you
|
||||
include the version of the object in the cache key, even object changes
|
||||
don't need any invalidation. You can force disable the cache though,
|
||||
e.g. in development mode.
|
||||
|
||||
:::php
|
||||
// Disables all caches
|
||||
SS_Cache::set_cache_lifetime('any', -1, 100);
|
||||
|
||||
You can also specifically clean a cache.
|
||||
Keep in mind that `Zend_Cache::CLEANING_MODE_ALL` deletes all cache
|
||||
entries across all caches, not just for the 'foo' cache in the example below.
|
||||
|
||||
:::php
|
||||
$cache = SS_Cache::factory('foo');
|
||||
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
|
||||
|
||||
A single element can be invalidated through its cache key.
|
||||
|
||||
:::php
|
||||
$cache = SS_Cache::factory('foo');
|
||||
$cache->remove($cachekey);
|
||||
|
||||
In order to increase the chance of your cache actually being hit,
|
||||
it often pays to increase the lifetime of caches ("TTL").
|
||||
It defaults to 10 minutes (600s) in SilverStripe, which can be
|
||||
quite short depending on how often your data changes.
|
||||
Keep in mind that data expiry should primarily be handled by your cache key,
|
||||
e.g. by including the `LastEdited` value when caching `DataObject` results.
|
||||
|
||||
:::php
|
||||
// set all caches to 3 hours
|
||||
SS_Cache::set_cache_lifetime('any', 60*60*3);
|
||||
|
||||
## Alternative Cache Backends
|
||||
|
||||
By default, SilverStripe uses a file-based caching backend.
|
||||
Together with a file stat cache like [APC](http://us2.php.net/manual/en/book.apc.php)
|
||||
this is reasonably quick, but still requires access to slow disk I/O.
|
||||
The `Zend_Cache` API supports various caching backends ([list](http://framework.zend.com/manual/1.12/en/zend.cache.backends.html))
|
||||
which can provide better performance, including APC, Xcache, ZendServer, Memcached and SQLite.
|
||||
|
||||
### Memcached
|
||||
|
||||
This backends stores cache records into a [memcached](http://www.danga.com/memcached/)
|
||||
server. memcached is a high-performance, distributed memory object caching system.
|
||||
To use this backend, you need a memcached daemon and the memcache PECL extension.
|
||||
|
||||
:::php
|
||||
// _config.php
|
||||
SS_Cache::add_backend(
|
||||
'primary_memcached',
|
||||
'Memcached',
|
||||
array(
|
||||
'host' => 'localhost',
|
||||
'port' => 11211,
|
||||
'persistent' => true,
|
||||
'weight' => 1,
|
||||
'timeout' => 5,
|
||||
'retry_interval' => 15,
|
||||
'status' => true,
|
||||
'failure_callback' => ''
|
||||
)
|
||||
);
|
||||
SS_Cache::pick_backend('primary_memcached', 'any', 10);
|
||||
|
||||
### APC
|
||||
|
||||
This backends stores cache records in shared memory through the [APC](http://pecl.php.net/package/APC)
|
||||
(Alternative PHP Cache) extension (which is of course need for using this backend).
|
||||
|
||||
:::php
|
||||
SS_Cache::add_backend('primary_apc', 'APC');
|
||||
SS_Cache::pick_backend('primary_apc', 'any', 10);
|
||||
|
||||
### Two-Levels
|
||||
|
||||
This backend is an hybrid one. It stores cache records in two other backends:
|
||||
a fast one (but limited) like Apc, Memcache... and a "slow" one like File or Sqlite.
|
||||
|
||||
:::php
|
||||
SS_Cache::add_backend('two_level', 'Two-Levels', array(
|
||||
'slow_backend' => 'File',
|
||||
'fast_backend' => 'APC',
|
||||
'slow_backend_options' => array(
|
||||
'cache_dir' => TEMP_FOLDER . DIRECTORY_SEPARATOR . 'cache'
|
||||
)
|
||||
));
|
||||
SS_Cache::pick_backend('two_level', 'any', 10);
|
@ -43,19 +43,24 @@ class Aggregate extends ViewableData {
|
||||
protected static function cache() {
|
||||
return self::$cache ? self::$cache : (self::$cache = SS_Cache::factory('aggregate'));
|
||||
}
|
||||
|
||||
/** Clear the aggregate cache for a given type, or pass nothing to clear all aggregate caches */
|
||||
|
||||
/**
|
||||
* Clear the aggregate cache for a given type, or pass nothing to clear all aggregate caches.
|
||||
* {@link $class} is just effective if the cache backend supports tags.
|
||||
*/
|
||||
public static function flushCache($class=null) {
|
||||
$cache = self::cache();
|
||||
|
||||
if (!$class || $class == 'DataObject') {
|
||||
$capabilities = $cache->getBackend()->getCapabilities();
|
||||
if($capabilities['tags'] && (!$class || $class == 'DataObject')) {
|
||||
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('aggregate'));
|
||||
} else {
|
||||
} elseif($capabilities['tags']) {
|
||||
$tags = ClassInfo::ancestry($class);
|
||||
foreach($tags as &$tag) {
|
||||
$tag = preg_replace('/[^a-zA-Z0-9_]/', '_', $tag);
|
||||
}
|
||||
$cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags);
|
||||
} else {
|
||||
$cache->clean(Zend_Cache::CLEANING_MODE_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user