-
-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Added the documentation for the Cache component #6515
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 21 commits
7582785
21da04e
05b7ba9
401410d
6acd591
b1c5b12
c6917bd
fc84df8
599ed0a
687910d
2d71222
6d21b01
e1bce89
81ec988
c44b7c2
11549e2
930a2d1
94011a7
cf07d4a
f2234ed
1628349
657659f
50f0d58
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
.. index:: | ||
single: Cache Item | ||
single: Cache Expiration | ||
single: Cache Exceptions | ||
|
||
Cache Items | ||
=========== | ||
|
||
Cache items are the information units stored in the cache as a key/value pair. | ||
In the Cache component they are represented by the | ||
:class:`Symfony\\Component\\Cache\\CacheItem` class. | ||
|
||
Cache Item Keys and Values | ||
-------------------------- | ||
|
||
The **key** of a cache item is a UTF-8 encoded string which acts as its | ||
identifier, so it must be unique for each cache pool. You can freely choose the | ||
keys, but they should only contain letters (A-Z, a-z), numbers (0-9) and the | ||
``_`` and ``.`` symbols. Other common symbols (such as ``{``, ``}``, ``(``, | ||
``)``, ``/``, ``\`` and ``@``) are reserved by the PSR-6 standard for future | ||
uses. | ||
|
||
The **value** of a cache item can be any data represented by a type which is | ||
serializable by PHP, such as basic types (string, integer, float, boolean, null), | ||
arrays and objects. | ||
|
||
Creating Cache Items | ||
-------------------- | ||
|
||
Cache items are created with the ``getItem($key)`` method of the cache pool. The | ||
argument is the key of the item:: | ||
|
||
// $cache pool object was created before | ||
$numProducts = $cache->getItem('stats.num_products'); | ||
|
||
Then, use the :method:`Psr\\Cache\\CacheItemInterface::set` method to set | ||
the data stored in the cache item:: | ||
|
||
// storing a simple integer | ||
$numProducts->set(4711); | ||
|
||
// storing an array | ||
$numProducts->set(array( | ||
'category1' => 4711, | ||
'category2' => 2387, | ||
)); | ||
|
||
.. note:: | ||
|
||
Creating a cache item and setting its value is not enough to save it in the | ||
cache. You must execute the ``save()`` method explicitly on the cache pool. | ||
|
||
The key and the value of any given cache item can be obtained with the | ||
corresponding *getter* methods:: | ||
|
||
$cacheItem = $cache->getItem('exchange_rate'); | ||
// ... | ||
$key = $cacheItem->getKey(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a difference between |
||
$value = $cacheItem->get(); | ||
|
||
Cache Item Expiration | ||
~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
By default cache items are stored permanently. In practice, this "permanent | ||
storage" can vary greatly depending on the type of cache being used, as | ||
explained in the :doc:`/components/cache/cache_pools` article. | ||
|
||
However, in some applications it's common to use cache items with a shorter | ||
lifespan. Consider for example an application which caches the latest news just | ||
for one minute. In those cases, use the ``expiresAfter()`` method to set the | ||
number of seconds to cache the item:: | ||
|
||
$latestNews = $cache->getItem('latest_news'); | ||
$latestNews->expiresAfter(60); // 60 seconds = 1 minute | ||
|
||
// this method also accepts \DateInterval instances | ||
$latestNews->expiresAfter(DateInterval::createFromDateString('1 hour')); | ||
|
||
Cache items define another related method called ``expiresAt()`` to set the | ||
exact date and time when the item will expire:: | ||
|
||
$mostPopularNews = $cache->getItem('popular_news'); | ||
$mostPopularNews->expiresAt(new \DateTime('tomorrow')); | ||
|
||
Cache Item Hits and Misses | ||
-------------------------- | ||
|
||
Using a cache mechanism is important to improve the application performance, but | ||
it should not be required to make the application work. In fact, the PSR-6 | ||
standard states that caching errors should not result in application failures. | ||
|
||
In practice this means that the ``getItem()`` method always returns an object | ||
which implements the ``Psr\Cache\CacheItemInterface`` interface, even when the | ||
cache item doesn't exist. Therefore, you don't have to deal with ``null`` return | ||
values and you can safely store in the cache values such as ``false`` and ``null``. | ||
|
||
In order to decide if the returned object is correct or not, caches use the | ||
concept of hits and misses: | ||
|
||
* **Cache Hits** occur when the requested item is found in the cache, its value | ||
is not corrupted or invalid and it hasn't expired; | ||
* **Cache Misses** are the opposite of hits, so they occur when the item is not | ||
found in the cache, its value is corrupted or invalid for any reason or the | ||
item has expired. | ||
|
||
Cache item objects define a boolean ``isHit()`` method which returns ``true`` | ||
for cache hits:: | ||
|
||
$latestNews = $cache->getItem('latest_news'); | ||
|
||
if (!$latestNews->isHit()) { | ||
// do some heavy computation | ||
$news = ...; | ||
$cache->save($latestNews->set($news)); | ||
} else { | ||
$news = $latestNews->get(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
.. index:: | ||
single: Cache Pool | ||
single: APC Cache, APCu Cache | ||
single: Doctrine Cache | ||
single: Redis Cache | ||
|
||
Cache Pools | ||
=========== | ||
|
||
Cache Pools are the logical repositories of cache items. They perform all the | ||
common operations on items, such as saving them or looking for them. Cache pools | ||
are independent from the actual cache implementation. Therefore, applications | ||
can keep using the same cache pool even if the underlying cache mechanism | ||
changes from a file system based cache to a Redis or database based cache. | ||
|
||
Creating Cache Pools | ||
-------------------- | ||
|
||
Cache Pools are created through the **cache adapters**, which are classes that | ||
implement the :class:`Psr\\Cache\\CacheItemPoolInterface` interface. This | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "which" refers to "cache adapters", these implement AdapterInterface (which extends CacheItemPoolInterface). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand this comment. Please tell me how to reword this paragraph:
Thanks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the current situation, it seems like I need to implement There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true for symfony derivated adapters (AdapterInterface extends CacheItemPoolInterface) |
||
component provides several adapters ready to use in your applications. | ||
|
||
Array Cache Adapter | ||
~~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter is only useful for testing purposes because contents are stored in | ||
memory and not persisted in any way. Besides, some features explained later are | ||
not available, such as the deferred saves:: | ||
|
||
use Symfony\Component\Cache\Adapter\ArrayAdapter; | ||
|
||
$cache = new ArrayAdapter( | ||
// in seconds; applied to cache items that don't define their own lifetime | ||
// 0 means to store the cache items indefinitely (i.e. until the current PHP process finishes) | ||
$defaultLifetime = 0, | ||
// if ``true``, the values saved in the cache are serialized before storing them | ||
$storeSerialized = true | ||
); | ||
|
||
Filesystem Cache Adapter | ||
~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter is useful when you want to improve the application performance but | ||
can't install tools like APC or Redis in the server. This adapter stores the | ||
contents as regular files in a set of directories on the local file system:: | ||
|
||
use Symfony\Component\Cache\Adapter\FilesystemAdapter; | ||
|
||
$cache = new FilesystemAdapter( | ||
// the subdirectory of the main cache directory where cache items are stored | ||
$namespace = '', | ||
// in seconds; applied to cache items that don't define their own lifetime | ||
// 0 means to store the cache items indefinitely (i.e. until the files are deleted) | ||
$defaultLifetime = 0, | ||
// the main cache directory (the application needs read-write permissions on it) | ||
// if none is specified, a directory is created inside the system temporary directory | ||
$directory = null | ||
); | ||
|
||
APCu Cache Adapter | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter can increase the application performance very significantly, | ||
because contents are cached in the shared memory of your server, which is much | ||
faster than the file system. It requires to have installed and enabled the PHP | ||
APCu extension. It's not recommended to use it when performing lots of write and | ||
delete operations because it produces fragmentation in the APCu memory that can | ||
degrade performance significantly:: | ||
|
||
use Symfony\Component\Cache\Adapter\ApcuAdapter; | ||
|
||
$cache = new ApcuAdapter( | ||
// the string prefixed to the keys of the items stored in this cache | ||
$namespace = '', | ||
// in seconds; applied to cache items that don't define their own lifetime | ||
// 0 means to store the cache items indefinitely (i.e. until the APC memory is deleted) | ||
$defaultLifetime = 0, | ||
// if present, this string is added to the namespace to simplify the | ||
// invalidation of the entire cache (e.g. when deploying the application) | ||
$version = null | ||
); | ||
|
||
Redis Cache Adapter | ||
~~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter stores the contents in the memory of the server. Unlike the APCu | ||
adapter, it's not limited to the shared memory of the current server, so you can | ||
store contents in a cluster of servers if needed. | ||
|
||
It requires to have installed Redis and have created a connection that implements | ||
the ``\Redis``, ``\RedisArray``, ``\RedisCluster`` or ``\Predis`` classes:: | ||
|
||
use Symfony\Component\Cache\Adapter\RedisAdapter; | ||
|
||
$cache = new RedisAdapter( | ||
// the object that stores a valid connection to your Redis system | ||
\Redis $redisConnection, | ||
// the string prefixed to the keys of the items stored in this cache | ||
$namespace = '', | ||
// in seconds; applied to cache items that don't define their own lifetime | ||
// 0 means to store the cache items indefinitely (i.e. until the Redis memory is deleted) | ||
$defaultLifetime = 0 | ||
); | ||
|
||
Chain Cache Adapter | ||
~~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter allows to combine any number of the previous adapters. Cache items | ||
are fetched from the first adapter which contains them. Besides, cache items are | ||
saved in all the given adapters, so this is a simple way of creating a cache | ||
replication:: | ||
|
||
use Symfony\Component\Cache\Adapter\ApcuAdapter; | ||
use Symfony\Component\Cache\Adapter\ChainAdapter; | ||
use Symfony\Component\Cache\Adapter\FilesystemAdapter; | ||
|
||
$apcCache = new ApcuAdapter(); | ||
$fileCache = new FilesystemAdapter(); | ||
|
||
$cache = new ChainAdapter(array($apcCache, $fileCache)); | ||
|
||
When an item is not found in the first adapters but is found in the next ones, | ||
the ``ChainAdapter`` ensures that the fetched item is saved in all the adapters | ||
where it was missing. Since it's not possible to know the expiry date and time | ||
of a cache item, the second optional argument of ``ChainAdapter`` is the default | ||
lifetime applied to those cache items (by default it's ``0``). | ||
|
||
Proxy Cache Adapter | ||
~~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter is useful to integrate in your application cache pools not created | ||
with the Symfony Cache component. As long as those cache pools implement the | ||
``CacheItemPoolInterface`` interface, this adapter allows you to get items from | ||
that external cache and save them in the Symfony cache of your application:: | ||
|
||
use Symfony\Component\Cache\Adapter\ProxyAdapter; | ||
|
||
// ... create $nonSymfonyCache somehow | ||
$cache = new ProxyAdapter($nonSymfonyCache); | ||
|
||
The adapter accepts two additional optional arguments: the namespace (``''`` by | ||
default) and the default lifetime (``0`` by default). | ||
|
||
Another use case for this adapter is to get statistics and metrics about the | ||
cache hits (``getHits()``) and misses (``getMisses()``). | ||
|
||
Doctrine Cache Adapter | ||
~~~~~~~~~~~~~~~~~~~~~~ | ||
|
||
This adapter wraps any `Doctrine Cache`_ provider so you can use them in your | ||
application as if they were Symfony Cache adapters:: | ||
|
||
use Doctrine\Common\Cache\SQLite3Cache; | ||
use Symfony\Component\Cache\Adapter\DoctrineAdapter; | ||
|
||
$doctrineCache = new SQLite3(__DIR__.'/cache/data.sqlite'); | ||
$symfonyCache = new DoctrineAdapter($doctrineCache); | ||
|
||
This adapter also defines two optional arguments called ``namespace`` (default: | ||
``''``) and ``defaultLifetime`` (default: ``0``) and adapts them to make them | ||
work in the underlying Doctrine cache. | ||
|
||
Looking for Cache Items | ||
----------------------- | ||
|
||
Cache Pools define three methods to look for cache items. The most common method | ||
is ``getItem($key)``, which returns the cache item identified by the given key:: | ||
|
||
use Symfony\Component\Cache\Adapter\FilesystemAdapter; | ||
|
||
$cache = new FilesystemAdapter('app.cache') | ||
$latestNews = $cache->getItem('latest_news'); | ||
|
||
If no item is defined for the given key, the method doesn't return a ``null`` | ||
value but an empty object which implements the :class:`Symfony\\Component\\Cache\\CacheItem` | ||
class. | ||
|
||
If you need to fetch several cache items simultaneously, use instead the | ||
``getItems(array($key1, $key2, ...))`` method:: | ||
|
||
// ... | ||
$stocks = $cache->getItems(array('AAPL', 'FB', 'GOOGL', 'MSFT')); | ||
|
||
Again, if any of the keys doesn't represent a valid cache item, you won't get | ||
a ``null`` value but an empty ``CacheItem`` object. | ||
|
||
The last method related to fetching cache items is ``hasItem($key)``, which | ||
returns ``true`` if there is a cache item identified by the given key:: | ||
|
||
// ... | ||
$hasBadges = $cache->hasItem('user_'.$userId.'_badges'); | ||
|
||
Saving Cache Items | ||
------------------ | ||
|
||
The most common method to save cache items is | ||
:method:`Psr\\Cache\\CacheItemPoolInterface::save`, which stores the | ||
item in the cache immediately (it returns ``true`` if the item was saved or | ||
``false`` if some error occurred):: | ||
|
||
// ... | ||
$userFriends = $cache->get('user_'.$userId.'_friends'); | ||
$userFriends->set($user->getFriends()); | ||
$isSaved = $cache->save($userFriends); | ||
|
||
Sometimes you may prefer to not save the objects immediately in order to | ||
increase the application performance. In those cases, use the | ||
:method:`Psr\\Cache\\CacheItemPoolInterface::saveDeferred` method to mark cache | ||
items as "ready to be persisted" and then call to | ||
:method:`Psr\\Cache\\CacheItemPoolInterface::commit` method when you are ready | ||
to persist them all:: | ||
|
||
// ... | ||
$isQueued = $cache->saveDeferred($userFriends); | ||
// ... | ||
$isQueued = $cache->saveDeferred($userPreferences); | ||
// ... | ||
$isQueued = $cache->saveDeferred($userRecentProducts); | ||
// ... | ||
$isSaved = $cache->commit(); | ||
|
||
The ``saveDeferred()`` method returns ``true`` when the cache item has been | ||
successfully added to the "persist queue" and ``false`` otherwise. The ``commit()`` | ||
method returns ``true`` when all the pending items are successfully saved or | ||
``false`` otherwise. | ||
|
||
Removing Cache Items | ||
-------------------- | ||
|
||
Cache Pools include methods to delete a cache item, some of them or all of them. | ||
The most common is :method:`Psr\\Cache\\CacheItemPoolInterface::deleteItem`, | ||
which deletes the cache item identified by the given key (it returns ``true`` | ||
when the item is successfully deleted or doesn't exist and ``false`` otherwise):: | ||
|
||
// ... | ||
$isDeleted = $cache->deleteItem('user_'.$userId); | ||
|
||
Use the :method:`Psr\\Cache\\CacheItemPoolInterface::deleteItems` method to | ||
delete several cache items simultaneously (it returns ``true`` only if all the | ||
items have been deleted, even when any or some of them don't exist):: | ||
|
||
// ... | ||
$areDeleted = $cache->deleteItems(array('category1', 'category2')); | ||
|
||
Finally, to remove all the cache items stored in the pool, use the | ||
:method:`Psr\\Cache\\CacheItemPoolInterface::clear` method (which returns ``true`` | ||
when all items are successfully deleted):: | ||
|
||
// ... | ||
$cacheIsEmpty = $cache->clear(); | ||
|
||
.. _`Doctrine Cache`: https://github.com/doctrine/cache |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
Cache | ||
===== | ||
|
||
.. toctree:: | ||
:maxdepth: 2 | ||
|
||
introduction | ||
cache_items | ||
cache_pools |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not showing this directly in the example above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@javiereguiluz What do you think about this? Besides this to me this one is ready to be merged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've implemented this change.