123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439 |
- Caching
- =======
- 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
- `in the PHP Documentation <http://us2.php.net/apc>`_. 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.
- .. code-block:: php
- <?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
- ` on the PHP website <http://us2.php.net/memcache>`_. 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.
- .. code-block:: php
- <?php
- $memcache = new Memcache();
- $memcache->connect('memcache_host', 11211);
-
- $cacheDriver = new \Doctrine\Common\Cache\MemcacheCache();
- $cacheDriver->setMemcache($memcache);
- $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.
- .. code-block:: php
- <?php
- $cacheDriver = new \Doctrine\Common\Cache\XcacheCache();
- $cacheDriver->save('cache_id', 'my_data');
- Redis
- ~~~~~
- In order to use the Redis cache driver you must have it compiled
- and enabled in your php.ini. You can read about what is Redis
- `from here <http://redis.io/>`_. Also check
- `A PHP extension for Redis <https://github.com/nicolasff/phpredis/>`_ for how you can use
- and install Redis PHP extension.
- Below is a simple example of how you could use the Redis cache
- driver by itself.
- .. code-block:: php
- <?php
- $redis = new Redis();
- $redis->connect('redis_host', 6379);
- $cacheDriver = new \Doctrine\Common\Cache\RedisCache();
- $cacheDriver->setRedis($redis);
- $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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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
- ^^^^^^^^^^^
- .. code-block:: php
- <?php
- $cacheDriver->delete('my_array');
- All
- ^^^
- If you simply want to delete all cache entries you can do so with
- the ``deleteAll()`` method.
- .. code-block:: php
- <?php
- $deleted = $cacheDriver->deleteAll();
- 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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?php
- $config->setResultCacheImpl(new \Doctrine\Common\Cache\ApcCache());
- Now when you're executing DQL queries you can configure them to use
- the result cache.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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()``.
- .. code-block:: php
- <?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.
- .. code-block:: php
- <?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.
- .. code-block:: php
- $ ./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.
- .. code-block:: php
- $ ./doctrine clear-cache --query
- To clear the metadata cache use the ``--metadata`` option.
- .. code-block:: php
- $ ./doctrine clear-cache --metadata
- To clear the result cache use the ``--result`` option.
- .. code-block:: php
- $ ./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.
- .. code-block:: php
- $ ./doctrine clear-cache --result --id=cache_id
- Or if you want to clear based on a regular expressions.
- .. code-block:: php
- $ ./doctrine clear-cache --result --regex=users_.*
- Or with a prefix.
- .. code-block:: php
- $ ./doctrine clear-cache --result --prefix=users_
- And finally with a suffix.
- .. code-block:: php
- $ ./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
- `in this blog post <http://notmysock.org/blog/php/user-cache-timebomb.html>`_.
|