Cache Component


    The Phalcon\Cache namespace offers a Cache component, that implements the interface, making it compatible with any component that requires that interface for its cache.

    Frequently used data or already processed/calculated data, can be stored in a cache storage for easier and faster retrieval. Since Phalcon\Cache components are written in Zephir, and therefore compiled as C code, they can achieve higher performance, while reducing the overhead that comes with getting data from any storage container. Some examples that warrant the use of cache are:

    • You are making complex calculations and the output does not change frequently
    • You are producing HTML using the same data all the time (same HTML)
    • You are accessing database data constantly which does not change often.

    components rely on components. Phalcon\Storage is split into two categories: Serializers and Adapters.

    Cache

    In order to instantiate a new component, you will need to pass a Phalcon\Cache\Adapter* class in it or one that implements the Phalcon\Cache\Adapter\AdapterInterface. For a detailed explanation on adapters and serializers, see below.

    Since the cache component is compatible it implements all the necessary methods to satisfy the PSR-16 interfaces. Each Cache component contains a supplied Cache adapter which in turn is responsible for all operations.

    get - getMultiple

    To get data from the cache you need to call the get() method with a key and a default value. If the key exists or it has not been expired, the data stored in it will be returned. Alternatively the passed defaultValue will be returned (default null).

    1. $value = $cache->get('my-key');
    2. $value = $cache->get('my-key', 'default');

    If you wish to retrieve more than one key with one call, you can call getMultiple(), passing an array with the keys needed. The method will return an array of key => value pairs. Cache keys that do not exist or have expired will have defaultValue as a value (default null).

    1. $value = $cache->getMultiple(['my-key1', 'my-key2']);
    2. $value = $cache->getMultiple(['my-key1', 'my-key2'], 'default');

    has

    To check whether a key exists in the cache (or it has not expired) you can call the has() method. The method will return true if the key exists, or false otherwise.

    1. $exists = $cache->has('my-key');

    set - setMultiple

    To save the data in the cache, you will need to use the set() method. The method accepts the key we wish to store the data under and the value of the item to store. The data needs to be of a type that supports serialization i.e. PHP type or an object that implements serialization. The last (optional) parameter is the TTL (time to live) value for this item. This option might not always be available, if the underlying adapter does not support it. The method will return true if the key exists, or false otherwise. If even one key is not successfully stored, the method will return false.

    1. $result = $cache->setMultiple('my-key', $data);

    If you wish to store more than one element with one call, you can call setMultiple(), passing an array of key => value pairs for the multiple-set operation. As with set the last (optional) parameter is the TTL (time to live). The method will return true if the key exists, or false otherwise.

    1. $value = $cache->setMultiple(
    2. [
    3. 'my-key1' => $data1,
    4. 'my-key2' => $data2,
    5. ],
    6. 9600
    7. );

    delete - deleteMultiple - clear

    To delete an item from the cache you need to call the delete() method with a key. The method returns true on success and false on failure.`

    1. $result = $cache->delete('my-key');

    If you wish to delete more than one key with one call, you can call deleteMultiple(), passing an array with the keys needed. The method returns true on success and false on failure. If even one key is not successfully deleted, the method will return false.`

    1. $result = $cache->deleteMultiple(['my-key1', 'my-key2']);

    If you wish to clear all the keys, you can call the clear() method. The method returns true on success and false on failure.

    newInstance

    We can easily create a class using the new keyword. However Phalcon offers the Phalcon\Cache\CacheFactory class, so that developers can easily instantiate cache objects. The factory will accept a object which will in turn be used to instantiate the necessary Cache class with the selected adapter and options. The factory always returns a new instance of Phalcon\Cache.

    The example below shows how you can create a cache object using the Apcu adapter and Json serializer:

    1. <?php
    2. use Phalcon\Cache\CacheFactory;
    3. use Phalcon\Cache\AdapterFactory;
    4. use Phalcon\Storage\SerializerFactory;
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. ];
    9. $serializerFactory = new SerializerFactory();
    10. $adapterFactory = new AdapterFactory(
    11. $serializerFactory,
    12. $options
    13. );
    14. $cacheFactory = new CacheFactory($adapterFactory);
    15. $cache = $cacheFactory->newInstance('apcu');

    The Cache Factory also offers the load method, which accepts a configuration object. This object can be an array or a object, with directives that are used to set up the cache. The object requires the adapter element, as well as the options element with the necessary directives.

    Exceptions

    Any exceptions thrown in the Cache component will be of type which implements Psr\SimpleCache\CacheException. Additionally the which implements also the Psr\SimpleCache\CacheException. It is thrown when the data supplied to the component or any sub components is not valid. You can use these exceptions to selectively catch exceptions thrown only from this component.

    1. <?php
    2. use Phalcon\Cache\Exception\Exception;
    3. use Phalcon\Mvc\Controller;
    4. class IndexController extends Controller
    5. {
    6. public function index()
    7. {
    8. try {
    9. // Get some configuration values
    10. $this->cache->get('some-key');
    11. } catch (Exception $ex) {
    12. echo $ex->getMessage();
    13. }
    14. }
    15. }

    The Phalcon\Storage\Serializer namespace offers classes that implement the interface and thus expose the serialize and unserialize methods. The purpose of these classes is to transform the data before saving it to the storage and after retrieving it from the storage.

    The default serializer for all adapters is Phalcon\Storage\Serializer\Php which uses PHP’s serialize and unserialize methods. These methods can suit most applications. However the developer might want to use something more efficient such as igbinary which is faster and achieves a better compression.

    Base64

    This serializer uses the base64_encode and base64_decode methods to serialize data. The input must be of type string, therefore this serializer has obvious limitations

    Igbinary

    The igbinary serializes relies on the igbinary_serialize and igbinary_unserialize methods. Those methods are exposed via the PHP extension, which has to be installed and loaded on the target system.

    Json

    The JSON serializer uses json_encode and json_decode. The target system must have JSON support available for PHP.

    Msgpack

    Similar to igbinary the msgpack serializer uses msgpack_pack and msgpack_unpack for serializing and unserializing data. This, along with igbinary is one of the fastest and most efficient serializers. However, it requires that the msgpack PHP extension is loaded on the target system.

    None

    This serializer does not transform the data at all. Both its serialize and unserialize get and set the data without altering it.

    This is the default serializer. It uses PHP’s serialize and unserialize methods for data transformations.

    Custom

    Phalcon also offers the ` which can be implemented in a custom class. The class can offer the serialization you require.

    1. <?php
    2. namespace MyApp\Storage\Serializer;
    3. use Phalcon\Storage\Serializer\SerializerInterface;
    4. class Garble extends SerializerInterface
    5. {
    6. /**
    7. * Data storage
    8. *
    9. * @var string
    10. */
    11. private $data = '';
    12. /**
    13. * Return the stored data
    14. *
    15. * @return string
    16. */
    17. public function getData(): string
    18. {
    19. return $this->data;
    20. }
    21. /**
    22. * Serializes data
    23. */
    24. public function serialize(): string
    25. {
    26. return rot13($this->data);
    27. }
    28. /**
    29. * Set the data
    30. *
    31. * @var Garble
    32. *
    33. * @return Garble
    34. */
    35. public function setData($data): Garble
    36. {
    37. $this->data = (string) $data;
    38. return $this;
    39. }
    40. /**
    41. * Unserializes data
    42. */
    43. public function unserialize($data): void
    44. {
    45. $this->data = str_rot13($data);
    46. }
    47. }

    Using it:

    1. <?php
    2. namespace MyApp;
    3. use MyApp\Storage\Serializer\Garble;
    4. $data = 'I came, I saw, I conquered.';
    5. $garble = new Garble();
    6. $garble
    7. ->serialize()
    8. ;
    9. echo $garble->getData(); // "V pnzr, V fnj, V pbadhrerq."
    10. $encrypted = 'V pnzr, V fnj, V pbadhrerq.';
    11. $garble->unserialize($encrypted);
    12. echo $garble->getData(); // "I came, I saw, I conquered."

    Serializer Factory

    Although all serializer classes can be instantiated using the new keyword, Phalcon offers the class, so that developers can easily instantiate serializer classes. All the above serializers are registered in the factory and lazy loaded when called. The factory also allows you to register additional (custom) serializer classes. The only thing to consider is choosing the name of the serializer in comparison to the existing ones. If you define the same name, you will overwrite the built in one.The objects are cached in the factory so if you call the newInstance() method with the same parameters during the same request, you will get the same object back.

    The example below shows how you can create a Json serializer either using the new keyword or the factory:

    1. <?php
    2. use Phalcon\Storage\Serializer\Json;
    3. use Phalcon\Storage\SerializerFactory;
    4. $jsonSerializer = new Json();
    5. $factory = new SerializerFactory();
    6. $jsonSerializer = $factory->newInstance('json');

    The parameters you can use for the factory are:

    The Phalcon\Cache\Adapter namespace offers classes that implement the Phalcon\Cache\Adapter\AdapterInterface interface. It exposes common methods that are used to perform operations on the storage adapter or cache backend. These adapters act as wrappers to respective backend code.

    The available methdods are:

    To construct one of these objects, you will need to pass a object in the constructor and optionally some parameters required for the adapter of your choice. The list of options is outlined below.

    The available adapters are:

    Apcu

    This adapter uses Apcu to store the data. In order to use this adapter, you will need to have enabled in your target system. This class does not use an actual adapter, since the apcu functionality is exposed using the apcu_* PHP functions.

    OptionDefault
    defaultSerializerPhp
    lifetime3600
    serializernull
    prefixph-apcu-

    The following example demonstrates how to create a new Apcu cache adapter, which will use the Phalcon\Storage\Serializer\Json serializer and have a default lifetime of 7200.

    1. <?php
    2. use Phalcon\Cache\Adapter\Apcu;
    3. use Phalcon\Storage\Serializer\SerializerFactory;
    4. $serializerFactory = new SerializerFactory();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. ];
    9. $adapter = new Apcu($serializerFactory, $options);

    The above example used a object and the defaultSerializer option to tell the adapter to instantiate the relevant serializer. If you already have a serializer instantiated, you can pass null for the serializer factory, and set the serializer in the options as shown below:

    1. <?php
    2. use Phalcon\Cache\Adapter\Apcu;
    3. use Phalcon\Storage\Serializer\Json;
    4. $jsonSerializer = new Json();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'serializer' => $jsonSerializer,
    9. ];
    10. $adapter = new Apcu(null, $options);

    Libmemcached

    This adapter utilizes PHP’s extension to connect to Memcached servers. The adapter used is an instance of the Memcached class, created after the first event that requires the connection to be active.

    You can specify more than one server in the options array passed in the constructor. If SASL data is defined, the adapter will try to authenticate using the passed data. If there is an error in the options or the class cannot add one or more servers in the pool, a Phalcon\Storage\Exception will be thrown.

    1. <?php
    2. use Phalcon\Cache\Adapter\Libmemcached;
    3. use Phalcon\Storage\Serializer\SerializerFactory;
    4. $serializerFactory = new SerializerFactory();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'servers' => [
    9. 0 => [
    10. 'host' => '10.4.13.100',
    11. 'port' => 11211,
    12. 'weight' => 1,
    13. ],
    14. 1 => [
    15. 'host' => '10.4.13.110',
    16. 'port' => 11211,
    17. 'weight' => 5,
    18. ],
    19. ],
    20. ];
    21. $adapter = new Libmemcached($serializerFactory, $options);

    The above example used a Phalcon\Storage\SerializerFactory object and the defaultSerializer option to tell the adapter to instantiate the relevant serializer. If you already have a serializer instantiated, you can pass null for the serializer factory, and set the serializer in the options as shown below:

    1. <?php
    2. use Phalcon\Cache\Adapter\Libmemcached;
    3. use Phalcon\Storage\Serializer\Json;
    4. $jsonSerializer = new Json();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'serializer' => $jsonSerializer,
    9. 'servers' => [
    10. 0 => [
    11. 'host' => '10.4.13.100',
    12. 'port' => 11211,
    13. 'weight' => 1,
    14. ],
    15. 1 => [
    16. 'host' => '10.4.13.110',
    17. 'port' => 11211,
    18. 'weight' => 5,
    19. ],
    20. ],
    21. ];
    22. $adapter = new Libmemcached(null, $options);

    Serializers: The Memcached class which is the adapter that the uses, offers support for serializing out of the box. The built in serializers are:

    • \Memcached::SERIALIZER_PHP
    • \Memcached::SERIALIZER_JSON
    • \Memcached::SERIALIZER_IGBINARYThe igbinary built in serializer is only available if igbinary is present in the target system and extension is compiled with it.

    If the defaultSerializer or the selected serializer for Libmemcached is supported as a built in serializer (PHP, JSON, IGBINARY), the built in one will be used, resulting in more speed and less resource utilization.

    Memory

    This adapter uses the computer’s memory to store the data. As all data is stored in memory, there is no persistence, meaning that once the request is completed, the data is lost. This adapter can be used for testing or temporary storage during a particular request. The options available for the constructor are:

    OptionDefault
    defaultSerializerPhp
    lifetime3600
    serializernull
    prefixph-memo-

    The following example demonstrates how to create a new Memory cache adapter, which will use the serializer and have a default lifetime of 7200.

    The above example used a Phalcon\Storage\SerializerFactory object and the defaultSerializer option to tell the adapter to instantiate the relevant serializer. If you already have a serializer instantiated, you can pass null for the serializer factory, and set the serializer in the options as shown below:

    1. <?php
    2. use Phalcon\Cache\Adapter\Memory;
    3. use Phalcon\Storage\Serializer\Json;
    4. $jsonSerializer = new Json();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'serializer' => $jsonSerializer,
    9. ];
    10. $adapter = new Memory(null, $options);

    Redis

    This adapter utilizes PHP’s redis extension to connect to a Redis server. The adapter used is an instance of the Redis class, created after the first event that requires the connection to be active.

    If auth data is defined, the adapter will try to authenticate using the passed data. If there is an error in the options, or the server cannot connect or authenticate, a Phalcon\Storage\Exception will be thrown.

    The following example demonstrates how to create a new Redis cache adapter, which will use the serializer and have a default lifetime of 7200. It will use the 10.4.13.100 as the host, connect to port 6379 and select the index 1.

    1. <?php
    2. use Phalcon\Cache\Adapter\Redis;
    3. use Phalcon\Storage\Serializer\SerializerFactory;
    4. $serializerFactory = new SerializerFactory();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'host' => '10.4.13.100',
    9. 'port' => 6379,
    10. 'index' => 1,
    11. ];
    12. $adapter = new Redis($serializerFactory, $options);

    The above example used a Phalcon\Storage\SerializerFactory object and the defaultSerializer option to tell the adapter to instantiate the relevant serializer. If you already have a serializer instantiated, you can pass null for the serializer factory, and set the serializer in the options as shown below:

    1. <?php
    2. use Phalcon\Cache\Adapter\Redis;
    3. use Phalcon\Storage\Serializer\Json;
    4. $jsonSerializer = new Json();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'host' => '10.4.13.100',
    9. 'port' => 6379,
    10. 'index' => 1,
    11. ];
    12. $adapter = new Redis(null, $options);

    Serializers: The Redis class which is the adapter that the uses, offers support for serializing out of the box. The built in serializers are:

    • \Redis::SERIALIZER_NONE
    • \Redis::SERIALIZER_PHP
    • \Redis::SERIALIZER_IGBINARY
    • \Redis::SERIALIZER_MSGPACKThe igbinary and built in serializer is only available if igbinary is present in the target system and extension is compiled with it. The same applies to msgpack built in serializer. It is only available if msgpack is present in the target system and the extension is compiled with it.

    This adapter is the simplest to setup since it uses the target system’s file system (it only requires a cache path that is writeable). It is one of the slowest cache adapters since the data has to be written to the file system. Each file created corresponds to a key stored. The file contains additional metadata to calculate the lifetime of the cache element, resulting in additional reads and writes to the file system.

    OptionDefault
    defaultSerializerPhp
    lifetime3600
    serializernull
    prefixphstrm-
    cacheDir

    If the cacheDir is not defined a Phalcon\Storage\Exception will be thrown.

    The adapter utilizes logic to store files in separate sub directories based on the name of the key passed, thus avoiding the too many files in one folder limit present in Windows or Linux based systems.

    The following example demonstrates how to create a new Stream cache adapter, which will use the Phalcon\Storage\Serializer\Json serializer and have a default lifetime of 7200. It will store the cached data in /data/storage/cache.

    1. <?php
    2. use Phalcon\Cache\Adapter\Stream;
    3. use Phalcon\Storage\Serializer\SerializerFactory;
    4. $serializerFactory = new SerializerFactory();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'cacheDir' => '/data/storage/cache',
    9. ];
    10. $adapter = new Stream($serializerFactory, $options);

    The above example used a object and the defaultSerializer option to tell the adapter to instantiate the relevant serializer. If you already have a serializer instantiated, you can pass null for the serializer factory, and set the serializer in the options as shown below:

    1. <?php
    2. use Phalcon\Cache\Adapter\Stream;
    3. use Phalcon\Storage\Serializer\Json;
    4. $jsonSerializer = new Json();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'cacheDir' => '/data/storage/cache',
    9. ];
    10. $adapter = new Stream(null, $options);

    Custom

    Phalcon also offers the which can be implemented in a custom class. The class can offer the cache adapter functionality you require.

    1. <?php
    2. namespace MyApp\Cache\Adapter;
    3. use Phalcon\Cache\Adapter\AdapterInterface;
    4. class Custom extends AdapterInterface
    5. {
    6. /**
    7. * Flushes/clears the cache
    8. */
    9. public function clear(): bool
    10. {
    11. // Custom implementation
    12. }
    13. /**
    14. * Decrements a stored number
    15. */
    16. public function decrement(string $key, int $value = 1)
    17. {
    18. // Custom implementation
    19. }
    20. /**
    21. * Deletes data from the adapter
    22. */
    23. public function delete(string $key): bool
    24. {
    25. // Custom implementation
    26. }
    27. /**
    28. * Reads data from the adapter
    29. */
    30. public function get(string $key)
    31. {
    32. // Custom implementation
    33. }
    34. /**
    35. * Returns the already connected adapter or connects to the backend
    36. * server(s)
    37. */
    38. public function getAdapter()
    39. {
    40. // Custom implementation
    41. }
    42. /**
    43. * Returns all the keys stored
    44. */
    45. public function getKeys(): array
    46. {
    47. // Custom implementation
    48. }
    49. /**
    50. * Returns the prefix for the keys
    51. */
    52. public function getPrefix(): string
    53. {
    54. // Custom implementation
    55. }
    56. /**
    57. * Checks if an element exists in the cache
    58. */
    59. public function has(string $key): bool
    60. {
    61. // Custom implementation
    62. }
    63. /**
    64. * Increments a stored number
    65. */
    66. public function increment(string $key, int $value = 1)
    67. {
    68. // Custom implementation
    69. }
    70. /**
    71. * Stores data in the adapter
    72. */
    73. public function set(string $key, $value, $ttl = null): bool
    74. {
    75. // Custom implementation
    76. }
    77. }

    Using it:

    1. <?php
    2. namespace MyApp;
    3. use MyApp\Cache\Adapter\Custom;
    4. $custom = new Custom();
    5. $custom->set('my-key', $data);

    Adapter Factory

    Although all adapter classes can be instantiated using the new keyword, Phalcon offers the class, so that developers can easily instantiate cache adapter classes. All the above adapters are registered in the factory and lazy loaded when called. The factory also allows you to register additional (custom) adapter classes. The only thing to consider is choosing the name of the adapter in comparison to the existing ones. If you define the same name, you will overwrite the built in one. The objects are cached in the factory so if you call the newInstance() method with the same parameters during the same request, you will get the same object back.

    The example below shows how you can create a Apcu cache adapter the new keyword or the factory:

    1. <?php
    2. use Phalcon\Cache\Adapter\Apcu;
    3. use Phalcon\Storage\Serializer\Json;
    4. $jsonSerializer = new Json();
    5. $options = [
    6. 'defaultSerializer' => 'Json',
    7. 'lifetime' => 7200,
    8. 'serializer' => $jsonSerializer,
    9. ];
    10. $adapter = new Apcu(null, $options);