1
0
mirror of synced 2024-12-14 23:26:04 +03:00
doctrine2/manual/en/caching.txt
Jonathan H. Wage 1e7193134a -
2010-04-06 14:36:40 -04:00

350 lines
12 KiB
Plaintext

Doctrine provides cache drivers in the `Common` package for some of the most
popular caching implementations such as APC, Memcache and Xcache. We also provide
an `ArrayCache` driver which stores the data in a PHP array. Obviously, the cache
does not live between requests but this is useful for testing in a development
environment.
++ Cache Drivers
The cache drivers follow a simple interface that is defined in `Doctrine\Common\Cache\Cache`.
All the cache drivers extend a base class `Doctrine\Common\Cache\AbstractCache`
which implements the before mentioned interface.
The interface defines the following methods for you to publicly use.
* fetch($id) - Fetches an entry from the cache.
* contains($id) - Test if an entry exists in the cache.
* save($id, $data, $lifeTime = false) - Puts data into the cache.
* delete($id) - Deletes a cache entry.
Each driver extends the `AbstractCache` class which defines a few abstract
protected methods that each of the drivers must implement.
* _doFetch($id)
* _doContains($id)
* _doSave($id, $data, $lifeTime = false)
* _doDelete($id)
The public methods `fetch()`, `contains()`, etc. utilize the above protected methods
that are implemented by the drivers. The code is organized this way so that the
protected methods in the drivers do the raw interaction with the cache implementation
and the `AbstractCache` can build custom functionality on top of these methods.
+++ APC
In order to use the APC cache driver you must have it compiled and enabled in
your php.ini. You can read about APC [here](http://us2.php.net/apc) on the PHP
website. It will give you a little background information about what it is and
how you can use it as well as how to install it.
Below is a simple example of how you could use the APC cache driver by itself.
[php]
$cacheDriver = new \Doctrine\Common\Cache\ApcCache();
$cacheDriver->save('cache_id', 'my_data');
+++ Memcache
In order to use the Memcache cache driver you must have it compiled and enabled in
your php.ini. You can read about Memcache [here](http://us2.php.net/memcache) on
the PHP website. It will give you a little background information about what it is
and how you can use it as well as how to install it.
Below is a simple example of how you could use the Memcache cache driver by itself.
[php]
$memcache = new Memcache();
$memcache->connect('memcache_host', 11211);
$cacheDriver = new \Doctrine\Common\Cache\MemcacheCache();
$cacheDriver->setMemcache()
$cacheDriver->save('cache_id', 'my_data');
+++ Xcache
In order to use the Xcache cache driver you must have it compiled and enabled in
your php.ini. You can read about Xcache [here](http://xcache.lighttpd.net/). It
will give you a little background information about what it is and how you can
use it as well as how to install it.
Below is a simple example of how you could use the Xcache cache driver by itself.
[php]
$cacheDriver = new \Doctrine\Common\Cache\XcacheCache();
$cacheDriver->save('cache_id', 'my_data');
++ Using Cache Drivers
In this section we'll describe how you can fully utilize the API of the cache
drivers to save cache, check if some cache exists, fetch the cached data and
delete the cached data. We'll use the `ArrayCache` implementation as our
example here.
[php]
$cacheDriver = new \Doctrine\Common\Cache\ArrayCache();
+++ Saving
To save some data to the cache driver it is as simple as using the `save()` method.
[php]
$cacheDriver->save('cache_id', 'my_data');
The `save()` method accepts three arguments which are described below.
* `$id` - The cache id
* `$data` - The cache entry/data.
* `$lifeTime` - The lifetime. If != false, sets a specific lifetime for this cache entry (null => infinite lifeTime).
You can save any type of data whether it be a string, array, object, etc.
[php]
$array = array(
'key1' => 'value1',
'key2' => 'value2'
);
$cacheDriver->save('my_array', $array);
+++ Checking
Checking whether some cache exists is very simple, just use the `contains()` method.
It accepts a single argument which is the ID of the cache entry.
[php]
if ($cacheDriver->contains('cache_id')) {
echo 'cache exists';
} else {
echo 'cache does not exist';
}
+++ Fetching
Now if you want to retrieve some cache entry you can use the `fetch()` method. It
also accepts a single argument just like `contains()` which is the ID of the cache entry.
[php]
$array = $cacheDriver->fetch('my_array');
+++ Deleting
As you might guess, deleting is just as easy as saving, checking and fetching.
We have a few ways to delete cache entries. You can delete by an individual ID,
regular expression, prefix, suffix or you can delete all entries.
++++ By Cache ID
[php]
$cacheDriver->delete('my_array');
You can also pass wild cards to the `delete()` method and it will return an array
of IDs that were matched and deleted.
[php]
$deleted = $cacheDriver->delete('users_*');
++++ By Regular Expression
If you need a little more control than wild cards you can use a PHP regular
expression to delete cache entries.
[php]
$deleted = $cacheDriver->deleteByRegex('/users_.*/');
++++ By Prefix
Because regular expressions are kind of slow, if simply deleting by a prefix or
suffix is sufficient, it is recommended that you do that instead of using a regular
expression because it will be much faster if you have many cache entries.
[php]
$deleted = $cacheDriver->deleteByPrefix('users_');
++++ By Suffix
Just like we did above with the prefix you can do the same with a suffix.
[php]
$deleted = $cacheDriver->deleteBySuffix('_my_account');
++++ All
If you simply want to delete all cache entries you can do so with the `deleteAll()`
method.
[php]
$deleted = $cacheDriver->deleteAll();
+++ Counting
If you want to count how many entries are stored in the cache driver instance
you can use the `count()` method.
[php]
echo $cacheDriver->count();
> **NOTE**
> In order to use `deleteByRegex()`, `deleteByPrefix()`, `deleteBySuffix()`,
> `deleteAll()`, `count()` or `getIds()` you must enable an option for the cache
> driver to manage your cache IDs internally. This is necessary because APC,
> Memcache, etc. don't have any advanced functionality for fetching and deleting.
> We add some functionality on top of the cache drivers to maintain an index of
> all the IDs stored in the cache driver so that we can allow more granular deleting
> operations.
>
> [php]
> $cacheDriver->setManageCacheIds(true);
+++ Namespaces
If you heavily use caching in your application and utilize it in multiple parts
of your application, or use it in different applications on the same server you
may have issues with cache naming collisions. This can be worked around by using
namespaces. You can set the namespace a cache driver should use by using the
`setNamespace()` method.
[php]
$cacheDriver->setNamespace('my_namespace_');
++ Integrating with the ORM
The Doctrine ORM package is tightly integrated with the cache drivers to allow
you to improve performance of various aspects of Doctrine by just simply making
some additional configurations and method calls.
+++ Query Cache
It is highly recommended that in a production environment you cache the
transformation of a DQL query to its SQL counterpart. It doesn't make sense to
do this parsing multiple times as it doesn't change unless you alter the DQL
query.
This can be done by configuring the query cache implementation to use on your ORM
configuration.
[php]
$config = new \Doctrine\ORM\Configuration();
$config->setQueryCacheImpl(new \Doctrine\Common\Cache\ApcCache());
+++ Result Cache
The result cache can be used to cache the results of your queries so that we
don't have to query the database or hydrate the data again after the first time.
You just need to configure the result cache implementation.
[php]
$config->setResultCacheImpl(new \Doctrine\Common\Cache\ApcCache());
Now when you're executing DQL queries you can configure them to use the result cache.
[php]
$query = $em->createQuery('select u from \Entities\User u');
$query->useResultCache(true);
You can also configure an individual query to use a different result cache driver.
[php]
$query->setResultCacheDriver(new \Doctrine\Common\Cache\ApcCache());
> **NOTE**
> Setting the result cache driver on the query will automatically enable the
> result cache for the query. If you want to disable it pass false to
> `useResultCache()`.
>
> [php]
> $query->useResultCache(false);
If you want to set the time the cache has to live you can use the `setResultCacheLifetime()`
method.
[php]
$query->setResultCacheLifetime(3600);
The ID used to store the result set cache is a hash which is automatically generated
for you if you don't set a custom ID yourself with the `setResultCacheId()` method.
[php]
$query->setResultCacheId('my_custom_id');
You can also set the lifetime and cache ID by passing the values as the second
and third argument to `useResultCache()`.
[php]
$query->useResultCache(true, 3600, 'my_custom_id');
+++ Metadata Cache
Your class metadata can be parsed from a few different sources like YAML, XML,
Annotations, etc. Instead of parsing this information on each request we should
cache it using one of the cache drivers.
Just like the query and result cache we need to configure it first.
[php]
$config->setMetadataCacheImpl(new \Doctrine\Common\Cache\ApcCache());
Now the metadata information will only be parsed once and stored in the cache
driver.
++ Clearing the Cache
We've already shown you previously how you can use the API of the cache drivers
to manually delete cache entries. For your convenience we offer a command line task
for you to help you with clearing the query, result and metadata cache.
From the Doctrine command line you can run the following command.
$ ./doctrine clear-cache
Running this task with no arguments will clear all the cache for all the configured
drivers. If you want to be more specific about what you clear you can use the
following options.
To clear the query cache use the `--query` option.
$ ./doctrine clear-cache --query
To clear the metadata cache use the `--metadata` option.
$ ./doctrine clear-cache --metadata
To clear the result cache use the `--result` option.
$ ./doctrine clear-cache --result
When you use the `--result` option you can use some other options to be more
specific about what queries result sets you want to clear.
Just like the API of the cache drivers you can clear based on an ID, regular
expression, prefix or suffix.
$ ./doctrine clear-cache --result --id=cache_id
Or if you want to clear based on a regular expressions.
$ ./doctrine clear-cache --result --regex=users_.*
Or with a prefix.
$ ./doctrine clear-cache --result --prefix=users_
And finally with a suffix.
$ ./doctrine clear-cache --result --suffix=_my_account
> **NOTE**
> Using the `--id`, `--regex`, etc. options with the `--query` and `--metadata`
> are not allowed as it is not necessary to be specific about what you clear.
> You only ever need to completely clear the cache to remove stale entries.
++ Cache Slams
Something to be careful of when utilizing the cache drivers is cache slams. If
you have a heavily trafficked website with some code that checks for the existence
of a cache record and if it does not exist it generates the information and saves
it to the cache. Now if 100 requests were issued all at the same time and each one
sees the cache does not exist and they all try and insert the same cache entry
it could lock up APC, Xcache, etc. and cause problems. Ways exist to work around
this, like pre-populating your cache and not letting your users requests populate
the cache.
You can read more about cache slams [here](http://t3.dotgnu.info/blog/php/user-cache-timebomb).