Search by

blazon / psr11-symfony-cache

wshafer

Symfony Cache Component Factories for PSR-11

Package info

gitlab.com/blazon/psr11-symfony-cache

Issues

pkg:composer/blazon/psr11-symfony-cache

Statistics

Installs: 1 270

Dependents: 0

Suggesters: 0

Stars: 0

0.0.2 2021-07-19 20:25 UTC

This package is auto-updated.

Last update: 2026-10-10 16:20:49 UTC


README

codecov pipeline status

PSR-11 Symfony Cache

Symfony Cache Component Factories for PSR-11. Requires PHP 8.4 or newer and Symfony Cache 8.1 or newer.

Table of Contents

Installation

composer require blazon/psr11-symfony-cache

Usage

<?php
/** @var \Symfony\Component\Cache\Adapter\AdapterInterface $cache */
$cache = $container->get('other');

// The callable will only be executed on a cache miss.
$value = $cache->get('my_cache_key', function (\Symfony\Contracts\Cache\ItemInterface $item) {
    $item->expiresAfter(3600);

    // ... do some HTTP request or heavy computations
    $computedValue = 'foobar';

    return $computedValue;
});

echo $value; // 'foobar'

// ... and to remove the cache key
$cache->delete('my_cache_key');

Additional info can be found in the documentation

PSR-16 Simple Cache

To use a cache as a PSR-16 simple cache, register a service that points to Blazon\PSR11SymfonyCache\SimpleCacheFactory. It builds the cache of the same name from the caches config (including its logger), and wraps it in Symfony's Psr16Cache. Requires psr/simple-cache.

<?php
$container = new \Laminas\ServiceManager\ServiceManager([
    'factories' => [
        // PSR-16 cache using the "default" cache config
        'simpleCache' => \Blazon\PSR11SymfonyCache\SimpleCacheFactory::class,

        // PSR-16 cache using the "other" cache config
        'otherSimpleCache' => [\Blazon\PSR11SymfonyCache\SimpleCacheFactory::class, 'other'],
    ],
]);

/** @var \Psr\SimpleCache\CacheInterface $cache */
$cache = $container->get('simpleCache');

$cache->set('my_cache_key', 'foobar', 3600);
echo $cache->get('my_cache_key'); // 'foobar'

Like CacheFactory, it can also be called statically: SimpleCacheFactory::other($container). Each service is its own cache instance, separate from one built by CacheFactory for the same name.

Containers

Any PSR-11 container wil work. In order to do that you will need to add configuration and register a new service that points to Blazon\PSR11SymfonyCache\CacheFactory

Below are some specific container examples to get you started

Laminas Service Manager

// Create the container and define the services you'd like to use
$container = new \Laminas\ServiceManager\ServiceManager([
    'factories' => [
        // Cache using the default keys.
        'cache' => \Blazon\PSR11SymfonyCache\CacheFactory::class,

        // Cache using a different cache configuration
        'other' => [\Blazon\PSR11SymfonyCache\CacheFactory::class, 'other'],

        // PSR-16 simple cache using the default keys.
        'simpleCache' => \Blazon\PSR11SymfonyCache\SimpleCacheFactory::class,

        // Marshaller using the "compressed" marshaller configuration
        'compressedMarshaller' => [\Blazon\PSR11SymfonyCache\MarshallerFactory::class, 'compressed'],
    ],
    'services' => [
        // Config
        'config' => [
            'cache' => [
                'caches' => [
                    // At the bare minimum you must include a default cache.
                    'default' => [
                        'type' => 'array',
                    ],

                    // Some other cache.  Keys are the names for each cache
                    'other' => [
                        'type' => 'filesystem',
                        'options' => [
                            'directory' => '/tmp/laminas',
                            'marshaller' => 'compressedMarshaller',
                        ],
                    ],
                ],

                // Marshallers.  Keys are the names for each marshaller
                'marshallers' => [
                    'compressed' => [
                        'type' => 'deflate',
                    ],
                ],
            ],
        ],
    ],
]);

/** @var \Symfony\Component\Cache\Adapter\AdapterInterface $cache */
$cache = $container->get('other');

PHP-DI

use Blazon\PSR11SymfonyCache\CacheFactory;
use Blazon\PSR11SymfonyCache\MarshallerFactory;
use Blazon\PSR11SymfonyCache\SimpleCacheFactory;
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;

use function DI\factory;

$builder = new ContainerBuilder();
$builder->addDefinitions([
    // Cache using the default keys.
    'cache' => factory(CacheFactory::class),

    // Cache using a different cache configuration
    'other' => fn(ContainerInterface $c) => CacheFactory::other($c),

    // PSR-16 simple cache using the default keys.
    'simpleCache' => factory(SimpleCacheFactory::class),

    // Marshaller using the "compressed" marshaller configuration
    'compressedMarshaller' => fn(ContainerInterface $c) => MarshallerFactory::compressed($c),

    // Config
    'config' => [
        'cache' => [
            'caches' => [
                // At the bare minimum you must include a default cache.
                'default' => [
                    'type' => 'array',
                ],

                // Some other cache.  Keys are the names for each cache
                'other' => [
                    'type' => 'filesystem',
                    'options' => [
                        'directory' => '/tmp/php-di',
                        'marshaller' => 'compressedMarshaller',
                    ],
                ],
            ],

            // Marshallers.  Keys are the names for each marshaller
            'marshallers' => [
                'compressed' => [
                    'type' => 'deflate',
                ],
            ],
        ],
    ],
]);

$container = $builder->build();

/** @var \Symfony\Component\Cache\Adapter\AdapterInterface $cache */
$cache = $container->get('other');

League Container

use Blazon\PSR11SymfonyCache\CacheFactory;
use Blazon\PSR11SymfonyCache\MarshallerFactory;
use Blazon\PSR11SymfonyCache\SimpleCacheFactory;
use League\Container\Container;

$container = new Container();

// Cache using the default keys.
$container->addShared('cache', fn() => (new CacheFactory())($container));

// Cache using a different cache configuration
$container->addShared('other', fn() => CacheFactory::other($container));

// PSR-16 simple cache using the default keys.
$container->addShared('simpleCache', fn() => (new SimpleCacheFactory())($container));

// Marshaller using the "compressed" marshaller configuration
$container->addShared('compressedMarshaller', fn() => MarshallerFactory::compressed($container));

// Config
$container->add('config', [
    'cache' => [
        'caches' => [
            // At the bare minimum you must include a default cache.
            'default' => [
                'type' => 'array',
            ],

            // Some other cache.  Keys are the names for each cache
            'other' => [
                'type' => 'filesystem',
                'options' => [
                    'directory' => '/tmp/league',
                    'marshaller' => 'compressedMarshaller',
                ],
            ],
        ],

        // Marshallers.  Keys are the names for each marshaller
        'marshallers' => [
            'compressed' => [
                'type' => 'deflate',
            ],
        ],
    ],
]);

/** @var \Symfony\Component\Cache\Adapter\AdapterInterface $cache */
$cache = $container->get('other');

Frameworks

Any framework that use a PSR-11 should work fine. Below are some specific framework examples to get you started

Mezzio

You'll need to add configuration and register the services you'd like to use. There are number of ways to do that but the recommended way is to create a new config file config/autoload/cache.global.php

Configuration

config/autoload/cache.global.php

<?php
return [
    'dependencies' => [
        'factories' => [
            // Cache using the default keys.
            'cache' => \Blazon\PSR11SymfonyCache\CacheFactory::class,

            // Cache using a different cache configuration
            'other' => [\Blazon\PSR11SymfonyCache\CacheFactory::class, 'other'],

            // PSR-16 simple cache using the default keys.
            'simpleCache' => \Blazon\PSR11SymfonyCache\SimpleCacheFactory::class,

            // Marshaller using the "compressed" marshaller configuration
            'compressedMarshaller' => [\Blazon\PSR11SymfonyCache\MarshallerFactory::class, 'compressed'],
        ],
    ],

    'cache' => [
        'caches' => [
            // At the bare minimum you must include a default cache.
            'default' => [
                'type' => 'array',
            ],

            // Some other cache.  Keys are the names for each cache
            'other' => [
                'type' => 'filesystem',
                'options' => [
                    'directory' => 'data/cache',
                    'marshaller' => 'compressedMarshaller',
                ],
            ],
        ],

        // Marshallers.  Keys are the names for each marshaller
        'marshallers' => [
            'compressed' => [
                'type' => 'deflate',
            ],
        ],
    ],
];

Laminas

You'll need to add configuration and register the services you'd like to use. There are number of ways to do that but the recommended way is to create a new config file config/autoload/cache.global.php

Configuration

config/autoload/cache.global.php

<?php
return [
    'service_manager' => [
        'factories' => [
            // Cache using the default keys.
            'cache' => \Blazon\PSR11SymfonyCache\CacheFactory::class,

            // Cache using a different cache configuration
            'other' => [\Blazon\PSR11SymfonyCache\CacheFactory::class, 'other'],

            // PSR-16 simple cache using the default keys.
            'simpleCache' => \Blazon\PSR11SymfonyCache\SimpleCacheFactory::class,

            // Marshaller using the "compressed" marshaller configuration
            'compressedMarshaller' => [\Blazon\PSR11SymfonyCache\MarshallerFactory::class, 'compressed'],
        ],
    ],

    'cache' => [
        'caches' => [
            // At the bare minimum you must include a default cache.
            'default' => [
                'type' => 'array',
            ],

            // Some other cache.  Keys are the names for each cache
            'other' => [
                'type' => 'filesystem',
                'options' => [
                    'directory' => 'data/cache',
                    'marshaller' => 'compressedMarshaller',
                ],
            ],
        ],

        // Marshallers.  Keys are the names for each marshaller
        'marshallers' => [
            'compressed' => [
                'type' => 'deflate',
            ],
        ],
    ],
];

Symfony

The Symfony service container is a PSR-11 container, and the factory reads its config from the cache container parameter. The following config will get these factories registered and working in Symfony.

Configuration

config/services.yaml (or equivalent)

parameters:
    cache:
        caches:
            # At the bare minimum you must include a default cache.
            default:
                type: array

            # Some other cache.  Keys are the names for each cache
            other:
                type: filesystem
                options:
                    directory: '%kernel.cache_dir%/psr11'
                    marshaller: compressedMarshaller

        # Marshallers.  Keys are the names for each marshaller
        marshallers:
            compressed:
                type: deflate

Container Service Config

config/services.yaml

services:
    # Cache using the default keys.
    myCache:
        factory: 'Blazon\PSR11SymfonyCache\CacheFactory:__invoke'
        class: 'Symfony\Component\Cache\Adapter\AdapterInterface'
        arguments: ['@service_container']
        public: true

    # Cache using a different cache configuration
    otherCache:
        factory: ['Blazon\PSR11SymfonyCache\CacheFactory', __callStatic]
        class: 'Symfony\Component\Cache\Adapter\AdapterInterface'
        arguments: ['other', ['@service_container']]
        public: true

    # PSR-16 simple cache using the default keys.
    simpleCache:
        factory: 'Blazon\PSR11SymfonyCache\SimpleCacheFactory:__invoke'
        class: 'Psr\SimpleCache\CacheInterface'
        arguments: ['@service_container']
        public: true

    # Marshaller using the "compressed" marshaller configuration
    compressedMarshaller:
        factory: ['Blazon\PSR11SymfonyCache\MarshallerFactory', __callStatic]
        class: 'Symfony\Component\Cache\Marshaller\MarshallerInterface'
        arguments: ['compressed', ['@service_container']]
        public: true

    Blazon\PSR11SymfonyCache\CacheFactory:
        class: 'Blazon\PSR11SymfonyCache\CacheFactory'
        public: true

    Blazon\PSR11SymfonyCache\SimpleCacheFactory:
        class: 'Blazon\PSR11SymfonyCache\SimpleCacheFactory'
        public: true

Slim

Slim 4 doesn't ship its own container, so bring any PSR-11 container and hand it to AppFactory. This example uses PHP-DI.

composer require slim/slim slim/psr7 php-di/php-di

public/index.php

<?php
use Blazon\PSR11SymfonyCache\CacheFactory;
use Blazon\PSR11SymfonyCache\MarshallerFactory;
use Blazon\PSR11SymfonyCache\SimpleCacheFactory;
use DI\ContainerBuilder;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;
use Symfony\Component\Cache\Adapter\AdapterInterface;
use Symfony\Contracts\Cache\ItemInterface;

use function DI\factory;

require __DIR__ . '/../vendor/autoload.php';

$builder = new ContainerBuilder();
$builder->addDefinitions([
    // Cache using the default keys.
    'cache' => factory(CacheFactory::class),

    // Cache using a different cache configuration
    'other' => fn(ContainerInterface $c) => CacheFactory::other($c),

    // PSR-16 simple cache using the default keys.
    'simpleCache' => factory(SimpleCacheFactory::class),

    // Marshaller using the "compressed" marshaller configuration
    'compressedMarshaller' => fn(ContainerInterface $c) => MarshallerFactory::compressed($c),

    // Config
    'settings' => [
        'cache' => [
            'caches' => [
                // At the bare minimum you must include a default cache.
                'default' => [
                    'type' => 'array',
                ],

                // Some other cache.  Keys are the names for each cache
                'other' => [
                    'type' => 'filesystem',
                    'options' => [
                        'directory' => '/tmp/slim',
                        'marshaller' => 'compressedMarshaller',
                    ],
                ],
            ],

            // Marshallers.  Keys are the names for each marshaller
            'marshallers' => [
                'compressed' => [
                    'type' => 'deflate',
                ],
            ],
        ],
    ],
]);

AppFactory::setContainer($builder->build());
$app = AppFactory::create();

// Example usage
$app->get('/example', function (Request $request, Response $response) {
    /** @var AdapterInterface $cache */
    $cache = $this->get('other');

    // The callable will only be executed on a cache miss.
    $value = $cache->get('my_cache_key', function (ItemInterface $item) {
        $item->expiresAfter(3600);

        return 'foobar';
    });

    $response->getBody()->write($value);

    return $response;
});

$app->run();

Configuration

The factory looks for its configuration in the following places, in this order:

  1. The cache parameter of a Symfony container
  2. The cache key of the config service (Laminas, Mezzio, PHP-DI, ...)
  3. The cache key of the settings service (Slim)

Minimal Configuration

A minimal configuration would consist of at least defining one service and the "default" cache.

Minimal Example

(using Mezzio for the example)

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'array',
            ],
        ],
    ],
];

Using this setup you will be using the "default" cache with the array adapter.

Full Configuration

Note: A "default" cache is required.

Full Example

(using Mezzio for the example)

<?php

return [
    'dependencies' => [
        'factories' => [
            // Cache using the default keys.
            'cache' => \Blazon\PSR11SymfonyCache\CacheFactory::class,

            // Cache using a different cache configuration
            'other' => [\Blazon\PSR11SymfonyCache\CacheFactory::class, 'other'],

            // PSR-16 simple cache using the default keys.  See PSR-16 Simple Cache above
            'simpleCache' => \Blazon\PSR11SymfonyCache\SimpleCacheFactory::class,

            // PSR-16 simple cache using a different cache configuration
            'otherSimpleCache' => [\Blazon\PSR11SymfonyCache\SimpleCacheFactory::class, 'other'],

            // Marshaller using the "compressed" marshaller configuration.  See Marshallers below
            'compressedMarshaller' => [\Blazon\PSR11SymfonyCache\MarshallerFactory::class, 'compressed'],
        ],
    ],

    'cache' => [
        'caches' => [
            // At the bare minimum you must include a default cache.
            'default' => [
                'type' => 'array',     // Required : the adapter type, a FactoryInterface class name, or a cache service name
                'logger' => 'service', // Optional : a PSR-3 logger service.  See Logger below
                'options' => [],       // Optional : adapter options.  See Adapters below
            ],

            // Some other cache.  Keys are the names for each cache
            'other' => [
                'type' => 'redis',
                'options' => [
                    'dsn' => 'redis://localhost',
                    'marshaller' => 'compressedMarshaller', // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],

        // Optional : marshallers, built by the MarshallerFactory.  See Marshallers below
        'marshallers' => [
            'compressed' => [
                'type' => 'deflate',
            ],
        ],
    ],
];

Caches are configured under caches, and are built by CacheFactory, or by SimpleCacheFactory for a PSR-16 simple cache. Marshallers are configured under marshallers, and are built by MarshallerFactory.

Options with a value of the wrong type are ignored, and the adapter's default is used instead. For example, a defaultLifetime of '300' (a string) is ignored, so cast values that come from environment variables.

Logger

Symfony cache adapters log the errors they recover from, like a failed save or a lost connection, instead of throwing them. To see those errors, set logger to the name of a PSR-3 logger service in your container. blazon/psr11-monolog provides Monolog loggers for PSR-11 containers.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'redis',
                'logger' => 'my-logger-service', // Optional : a PSR-3 logger service.  Will be pulled from the container.
                'options' => [
                    'dsn' => 'redis://localhost',
                ],
            ],
        ],
    ],
];

The APCu, Array, Doctrine DBAL, Filesystem, Filesystem Tag Aware, Memcached, PDO, PHP Files, PSR-16, Redis, Redis Tag Aware and Tag Aware adapters support a logger. Setting a logger on the Chain, Null, PHP Array, Proxy, Traceable or Traceable Tag Aware adapters throws an InvalidConfigException.

Wrapped Caches

The Chain, PHP Array, Proxy, PSR-16, Tag Aware, Traceable and Traceable Tag Aware adapters wrap other caches. Each wrapped cache is configured with one of the following, checked in this order:

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'traceable',
                'options' => [
                    'pool' => [
                        // Required if no cache or type is provided : Service name of a cache in your container
                        'service' => 'myCacheService',

                        // Required if no service or type is provided : Name of another cache in this config
                        // to build and wrap
                        'cache' => 'other',

                        // Required if no service or cache is provided : Cache adapter to build and wrap
                        'type' => 'redis',
                        'options' => [                    // Optional : Options for the wrapped cache adapter
                            'dsn' => 'redis://localhost',
                        ],
                    ],
                ],
            ],
            'other' => [
                'type' => 'filesystem',
            ],
        ],
    ],
];

service is used first, then cache, then type and options. A cache built with cache or type is a new instance, separate from the one CacheFactory builds for that name, and only its type and options are used (its logger is not set).

Adapters

Example configs for supported adapters. The type is not case-sensitive.

APCu

This adapter is a high-performance, shared memory cache. It can significantly increase an application’s performance, as its cache contents are stored in shared memory, a component appreciably faster than many others, such as the filesystem. Requires the apcu extension.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'apcu',
                'options' => [
                    'namespace' => '',       // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,  // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'version' => null,       // Optional : a version string.  Changing it invalidates the cache.  Default: null
                    'marshaller' => null,    // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: APCu Cache Adapter

Array

Generally, this adapter is useful for testing purposes, as its contents are stored in memory and not persisted outside the running PHP process in any way. It can also be useful while warming up caches, due to the getValues() method

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'array',
                'options' => [
                    'defaultLifetime' => 0, // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'deepClone' => true,    // Optional : clone values (serializing objects) when storing and fetching them.  Default: true
                    'maxLifetime' => 0,     // Optional : the maximum lifetime (in seconds, int or float) of the entire cache.  Default: 0
                    'maxItems' => 0,        // Optional : the maximum number of items that can be stored in the cache.  Default: 0
                ],
            ],
        ],
    ],
];

Docs: Array Cache Adapter

Chain

This adapter allows combining any number of the other available cache adapters. Cache items are fetched from the first adapter containing them and cache items are saved to all the given adapters. This exposes a simple and efficient method for creating a layered cache.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'chain',
                'options' => [
                    // Required : The ordered list of caches.  See Wrapped Caches above
                    'adapters' => [
                        ['type' => 'apcu'],
                        ['service' => 'slow-cache'],
                    ],
                    'defaultLifetime' => 0, // Optional : The lifetime of items propagated from lower adapters to upper ones.  Default: 0
                ],
            ],
        ],
    ],
];

Docs: Chain Cache Adapter

Doctrine DBAL

This adapter stores the cache items in an SQL database using a Doctrine DBAL connection. Requires doctrine/dbal 4.3 or higher. The table is created on first use.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'doctrinedbal',
                'options' => [
                    'client' => 'service-name',           // Required : A \Doctrine\DBAL\Connection service name, or a DSN like "mysql://user:pass@localhost/cache"

                    'db_table' => 'cache_items',          // Optional.  The name of the table.  Default: cache_items
                    'db_id_col' => 'item_id',             // Optional.  The column where to store the cache id.  Default: item_id
                    'db_data_col' => 'item_data',         // Optional.  The column where to store the cache data.  Default: item_data
                    'db_lifetime_col' => 'item_lifetime', // Optional.  The column where to store the lifetime.  Default: item_lifetime
                    'db_time_col' => 'item_time',         // Optional.  The column where to store the timestamp.  Default: item_time

                    // Cache Config
                    'namespace' => '',                    // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,               // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,                 // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: Doctrine DBAL Cache Adapter

Filesystem

This adapter offers improved application performance for those who cannot install tools like APCu or Redis in their environment. It stores the cache item expiration and content as regular files in a collection of directories on a locally mounted filesystem.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'filesystem',
                'options' => [
                    'directory' => null,    // Optional : The main cache directory.  Default: a "symfony-cache" directory in the system temporary directory
                    'namespace' => '',      // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0, // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,   // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: Filesystem Cache Adapter

Filesystem Tag Aware

Works like the Filesystem adapter, and adds support for tag based invalidation. Tags are stored as symlinks on the filesystem, so invalidating a tag is fast.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'filesystemtagaware',
                'options' => [
                    'directory' => null,    // Optional : The main cache directory.  Default: a "symfony-cache" directory in the system temporary directory
                    'namespace' => '',      // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0, // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,   // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: Filesystem Cache Adapter

Memcached

This adapter stores the values in-memory using one (or more) Memcached server instances. Unlike the APCu adapter, and similarly to the Redis adapter, it is not limited to the current server’s shared memory; you can store contents independent of your PHP environment. The ability to utilize a cluster of servers to provide redundancy and/or fail-over is also available. Requires the memcached extension.

The connection option defaults are the ones Symfony uses when it creates the connection.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'memcached',
                'options' => [
                    // Connection config
                    // A client service, or dsn(s) is required.
                    'client' => 'service-name',          // A \Memcached service name.  Will be pulled from the container.
                    'dsn' => 'memcached://localhost',    // A DSN, or an array of DSNs for multiple servers

                    // Connection Options.  Not needed if using a client service.
                    'persistent_id' => null,             // Optional.  Default: null
                    'username' => null,                  // Optional.  SASL username.  Default: null
                    'password' => null,                  // Optional.  SASL password.  Default: null
                    'auto_eject_hosts' => false,         // Optional.  Default: false
                    'binary_protocol' => true,           // Optional.  Default: true
                    'buffer_writes' => false,            // Optional.  Default: false
                    'compression' => true,               // Optional.  Default: true
                    'compression_type' => null,          // Optional.  A \Memcached::COMPRESSION_* constant.  Default: the extension default
                    'connect_timeout' => 4000,           // Optional.  Default: 4000
                    'distribution' => null,              // Optional.  'modula', 'consistent' or 'virtual_bucket'.  Default: set by libketama_compatible
                    'hash' => null,                      // Optional.  'default', 'md5', 'crc', 'fnv1_64', 'fnv1a_64', 'fnv1_32', 'fnv1a_32', 'hsieh' or 'murmur'.  Default: set by libketama_compatible
                    'libketama_compatible' => true,      // Optional.  Default: true
                    'no_block' => true,                  // Optional.  Default: true
                    'number_of_replicas' => 0,           // Optional.  Default: 0
                    'poll_timeout' => 5000,              // Optional.  Default: 5000
                    'prefix_key' => '',                  // Optional.  Default: ''
                    'randomize_replica_read' => false,   // Optional.  Default: false
                    'recv_timeout' => 0,                 // Optional.  Default: 0
                    'retry_timeout' => 2,                // Optional.  Default: 2
                    'send_timeout' => 0,                 // Optional.  Default: 0
                    'serializer' => 'php',               // Optional.  'php' or 'igbinary'.  Default: php
                    'server_failure_limit' => 5,         // Optional.  Default: 5
                    'socket_recv_size' => null,          // Optional.  Default: varies by platform and kernel
                    'tcp_keepalive' => false,            // Optional.  Default: false
                    'tcp_nodelay' => true,               // Optional.  Default: true
                    'use_udp' => false,                  // Optional.  Default: false
                    'verify_key' => false,               // Optional.  Default: false

                    // Cache Config
                    'namespace' => '',                   // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,              // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,                // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: Memcached Cache Adapter

Null

This cache adapter stores nothing. Every item fetched is a cache miss, and saving an item does nothing. It is useful for disabling caching in an environment (such as testing) without changing the code that uses the cache.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'null',
            ],
        ],
    ],
];

Docs: Null Cache Adapter

PDO

This adapter stores the cache items in an SQL database. Requires the pdo extension and a driver for your database.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'pdo',
                'options' => [
                    'client' => 'service-name',                // Required : A \PDO service name, or a PDO DSN like "mysql:host=localhost;dbname=cache"

                    'db_table' => 'cache_items',               // Optional.  The name of the table.  Default: cache_items
                    'db_id_col' => 'item_id',                  // Optional.  The column where to store the cache id.  Default: item_id
                    'db_data_col' => 'item_data',              // Optional.  The column where to store the cache data.  Default: item_data
                    'db_lifetime_col' => 'item_lifetime',      // Optional.  The column where to store the lifetime.  Default: item_lifetime
                    'db_time_col' => 'item_time',              // Optional.  The column where to store the timestamp.  Default: item_time
                    'db_username' => null,                     // Optional.  The username when lazy-connect.  Default: null
                    'db_password' => null,                     // Optional.  The password when lazy-connect.  Default: null
                    'db_connection_options' => [],             // Optional.  An array of driver-specific connection options.  Default: []

                    // Cache Config
                    'namespace' => '',                         // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,                    // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,                      // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: PDO Cache Adapter

PHP Array

This adapter is a high performance cache for static data (e.g. application configuration) that is optimized and preloaded into OPcache memory storage. It is suited for any data that is mostly read-only after warmup.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'phparray',
                'options' => [
                    'filePath' => __DIR__ . '/somefile.cache', // Required: Single file where values are cached
                    'backupCache' => ['cache' => 'other'],      // Required: The cache used when a value is not in the file.  See Wrapped Caches above
                ],
            ],
        ],
    ],
];

Docs: PHP Array Cache Adapter

PHP Files

Similarly to Filesystem Adapter, this cache implementation writes cache entries out to disk, but unlike the Filesystem cache adapter, the PHP Files cache adapter writes and reads back these cache files as native PHP code.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'phpfiles',
                'options' => [
                    'directory' => null,    // Optional : The main cache directory (the application needs read-write permissions on it).  Default: a "symfony-cache" directory in the system temporary directory
                    'appendOnly' => false,  // Optional : set to true for extra performance when the items stored never expire.  Default: false

                    // Cache Config
                    'namespace' => '',      // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0, // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                ],
            ],
        ],
    ],
];

Docs: PHP Files Cache Adapter

Proxy

This adapter wraps a PSR-6 compliant cache item pool interface. It is used to integrate your application’s cache item pool implementation with the Symfony Cache Component by consuming any implementation of Psr\Cache\CacheItemPoolInterface.

It can also be used to prefix all keys automatically before storing items in the decorated pool, effectively allowing the creation of several namespaced pools out of a single one.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'proxy',
                'options' => [
                    'pool' => ['service' => 'service-name'], // Required: A PSR-6 cache.  See Wrapped Caches above

                    // Cache Config
                    'namespace' => '',                       // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,                  // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                ],
            ],
        ],
    ],
];

A service can be any Psr\Cache\CacheItemPoolInterface, not just a Symfony cache.

Docs: Proxy Cache Adapter

PSR-16

This adapter wraps a PSR-16 simple cache, so it can be used as a PSR-6 cache. Requires psr/simple-cache.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'psr16',
                'options' => [
                    'pool' => ['service' => 'service-name'], // Required: A PSR-16 cache.  See Wrapped Caches above

                    // Cache Config
                    'namespace' => '',                       // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,                  // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                ],
            ],
        ],
    ],
];

A service must be a Psr\SimpleCache\CacheInterface. A cache built with cache or type is a PSR-6 cache, so it is wrapped in Symfony's Psr16Cache first.

Docs: PSR-16 Cache Adapter

Redis

This adapter stores the values in-memory using one (or more) Redis server instances.

Unlike the APCu adapter, and similarly to the Memcached adapter, it is not limited to the current server’s shared memory; you can store contents independent of your PHP environment. The ability to utilize a cluster of servers to provide redundancy and/or fail-over is also available. Requires the redis or relay extension, or predis/predis.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'redis',
                'options' => [
                    // Connection config
                    // A client service, or dsn is required.
                    'client' => 'service-name',     // A \Redis, \RedisArray, \RedisCluster, Predis or Relay service name.  Will be pulled from the container.
                    'dsn' => 'redis://localhost',   // redis://[pass@][ip|host|socket[:port]][/db-index]

                    // Connection Options.  Not needed if using a client service.
                    'class' => null,                // Optional.  The connection class, e.g. \Redis, \Relay\Relay or \Predis\Client.  Default: picked from what is installed
                    'auth' => null,                 // Optional.  A password, or a [username, password] array.  Default: null
                    'persistent' => false,          // Optional.  Use persistent connections.  Default: false
                    'persistent_id' => null,        // Optional.  The persistent id string to use for a persistent connection.  Default: null
                    'timeout' => 30,                // Optional.  The timeout (in seconds) used to connect to a Redis server.  Default: 30
                    'read_timeout' => 0,            // Optional.  The read timeout (in seconds).  Default: 0
                    'retry_interval' => 0,          // Optional.  The delay (in milliseconds) between reconnection attempts.  Default: 0
                    'tcp_keepalive' => 0,           // Optional.  The TCP-keepalive timeout (in seconds) of the connection.  Default: 0
                    'lazy' => null,                 // Optional.  Connect on first use instead of right away.  Default: null
                    'cluster' => false,             // Optional.  Connect to a Redis cluster.  Default: false
                    'cluster_command_timeout' => 0, // Optional.  The command timeout for Relay clusters.  Default: 0
                    'cluster_relay_context' => [],  // Optional.  The stream context for Relay clusters.  Default: []
                    'sentinel' => null,             // Optional.  The Redis Sentinel master name.  Default: null
                    'dbindex' => 0,                 // Optional.  The database index.  Default: 0
                    'failover' => 'none',           // Optional.  Cluster failover: 'none', 'error', 'distribute' or 'slaves'.  Default: none
                    'ssl' => null,                  // Optional.  An array of SSL context options.  Default: null

                    // Cache Config
                    'namespace' => '',              // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,         // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,           // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: Redis Cache Adapter

Redis Tag Aware

Works like the Redis adapter, and adds support for tag based invalidation using Redis sets. It takes the same options as the Redis adapter. The Redis server must use a noeviction or volatile-* eviction policy, and compression must be disabled on phpredis and Relay clients (use the Deflate marshaller instead).

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'redistagaware',
                'options' => [
                    'dsn' => 'redis://localhost',  // A client service, or dsn is required.  See Redis above for all connection options

                    // Cache Config
                    'namespace' => '',             // Optional : a string prefixed to the keys of the items.  Default: ''
                    'defaultLifetime' => 0,        // Optional : the default lifetime (in seconds) for cache items.  Default: 0
                    'marshaller' => null,          // Optional : a marshaller service.  See Marshallers below
                ],
            ],
        ],
    ],
];

Docs: Redis Cache Adapter

Tag Aware

This adapter adds tag based invalidation to any other cache adapter. Items are stored in the items pool, and tag versions are stored in the tags pool.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'tagaware',
                'options' => [
                    'itemsPool' => ['type' => 'filesystem'], // Required : The cache to store the items in.  See Wrapped Caches above
                    'tagsPool' => ['type' => 'apcu'],        // Optional : The cache to store the tags in.  Default: the items pool
                    'knownTagVersionsTtl' => 0.15,           // Optional : How long (in seconds) tag versions are trusted before being checked again.  Default: 0.15
                ],
            ],
        ],
    ],
];

Docs: Cache Invalidation

Traceable

This adapter wraps another cache service, and records every call made to it along with its timing and hits or misses. It is meant for debugging and profiling.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'traceable',
                'options' => [
                    'pool' => ['cache' => 'other'], // Required : The cache to trace.  See Wrapped Caches above
                ],
            ],
        ],
    ],
];

Traceable Tag Aware

Works like the Traceable adapter, for a tag aware cache service.

<?php

return [
    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'traceabletagaware',
                'options' => [
                    'pool' => ['cache' => 'other'], // Required : The tag aware cache to trace.  See Wrapped Caches above
                ],
            ],
        ],
    ],
];

Marshallers

The APCu, Doctrine DBAL, Filesystem, Filesystem Tag Aware, Memcached, PDO, Redis and Redis Tag Aware adapters serialize values with a marshaller. To use a different one, for example to compress or encrypt values, set the marshaller adapter option to the name of a Symfony\Component\Cache\Marshaller\MarshallerInterface service in your container. When not set, Symfony's DefaultMarshaller is used.

Marshallers have their own factory, MarshallerFactory, and are configured under the marshallers key. It works just like CacheFactory: the "default" marshaller is used unless a different marshaller name is given. Register the marshaller as a service, then use that service name in the cache's marshaller option.

The Deflate, Sodium and Tag Aware marshallers wrap another marshaller. Their marshaller option is also a service name, so marshallers can be chained, e.g. values compressed and then encrypted.

Config

<?php

return [
    'dependencies' => [
        'factories' => [
            // Cache using the encrypted marshaller
            'cache' => \Blazon\PSR11SymfonyCache\CacheFactory::class,

            // Marshaller using the default marshaller config
            'compressedMarshaller' => \Blazon\PSR11SymfonyCache\MarshallerFactory::class,

            // Marshaller using a different marshaller config
            'encryptedMarshaller' => [\Blazon\PSR11SymfonyCache\MarshallerFactory::class, 'encrypted'],
        ],
    ],

    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'redis',
                'options' => [
                    'dsn' => 'redis://localhost',
                    'marshaller' => 'encryptedMarshaller',
                ],
            ],
        ],

        'marshallers' => [
            // Array keys are the names used for the marshaller
            'default' => [
                'type' => 'deflate',
            ],

            // Compress, then encrypt
            'encrypted' => [
                'type' => 'sodium',
                'options' => [
                    'decryptionKeys' => [base64_decode((string) getenv('CACHE_DECRYPTION_KEY'))],
                    'marshaller' => 'compressedMarshaller',
                ],
            ],
        ],
    ],
];

It can also be called statically with the marshaller name, like CacheFactory:

$marshaller = \Blazon\PSR11SymfonyCache\MarshallerFactory::encrypted($container);

The type is not case-sensitive. It can also be a Blazon\PSR11SymfonyCache\Marshaller\FactoryInterface class name, or the name of a marshaller service.

Docs: Marshalling (Serializing) Data

Default

Serializes values with PHP's serialize(), or igbinary. This is the marshaller the adapters use when none is set.

<?php

return [
    'cache' => [
        'marshallers' => [
            'default' => [
                'type' => 'default',
                'options' => [
                    'useIgbinarySerialize' => null,         // Optional : true to use igbinary (requires the igbinary extension).  Default: null (off)
                    'throwOnSerializationFailure' => false, // Optional : throw instead of skipping values that fail to serialize.  Default: false
                ],
            ],
        ],
    ],
];

Deflate

Compresses values with gzdeflate() after marshalling them. Requires the zlib extension.

<?php

return [
    'cache' => [
        'marshallers' => [
            'default' => [
                'type' => 'deflate',
                'options' => [
                    'marshaller' => 'service-name', // Optional : the marshaller service to compress.  Default: a DefaultMarshaller
                ],
            ],
        ],
    ],
];

Sodium

Encrypts values after marshalling them. Requires the sodium extension.

Each key must be generated with sodium_crypto_box_keypair(). Keys are binary, so store them encoded, for example with php -r 'echo base64_encode(sodium_crypto_box_keypair());', and decode them in your config. The first key encrypts and decrypts values. Any others only decrypt, so old keys can be rotated out.

<?php

return [
    'cache' => [
        'marshallers' => [
            'default' => [
                'type' => 'sodium',
                'options' => [
                    'decryptionKeys' => [                                    // Required : one or more keys
                        base64_decode((string) getenv('CACHE_DECRYPTION_KEY')),
                        base64_decode((string) getenv('CACHE_OLD_DECRYPTION_KEY')),
                    ],
                    'marshaller' => 'service-name',                          // Optional : the marshaller service to encrypt.  Default: a DefaultMarshaller
                ],
            ],
        ],
    ],
];

Tag Aware

Used by tag aware caches to store values and their tags. Symfony's tag aware adapters use it automatically.

<?php

return [
    'cache' => [
        'marshallers' => [
            'default' => [
                'type' => 'tagaware',
                'options' => [
                    'marshaller' => 'service-name', // Optional : the marshaller service to wrap.  Default: a DefaultMarshaller
                ],
            ],
        ],
    ],
];

Upgrades

Upgrading from 0.0.x

This release upgrades Symfony Cache to version 8.1 and requires PHP 8.4 or newer.

Backwards compatibility breaks

  • PHP 8.4 or newer is required.

  • Symfony Cache 8.1 or newer is required.

  • psr/container 1.1 or 2.0 is required.

  • The Couchbase and Doctrine adapters have been removed. Symfony removed the CouchbaseBucketAdapter and the DoctrineAdapter (doctrine/cache) they were built on.

  • Options have been renamed to match the Symfony constructor arguments:

    AdapterOld nameNew name
    ChainmaxLifetimedefaultLifetime
    Memcached, PDO, RedismaxLifetimedefaultLifetime
    ArraystoreSerializeddeepClone

    The Array adapter still has a maxLifetime option, which is the maximum lifetime of the entire cache.

  • The configuration has been restructured. Caches have moved into a caches key, which leaves room for the new marshallers key. The configuration key is cache. The previous documentation showed symfonyCache, which was never read.

    Version 0.0.x:

    'cache' => [
        'default' => [
            'type' => 'array',
        ],
    ],
    

    Now:

    'cache' => [
        'caches' => [
            'default' => [
                'type' => 'array',
            ],
        ],
    ],
    
  • Options with a value of the wrong type are now ignored, and the default is used instead. Previously values were cast, so a defaultLifetime of '300' (a string) was used as 300. Cast values that come from environment variables.

  • Redis:

    • The compression option has been removed. It is not a Symfony Redis option and was never used.
    • persistent is now a boolean.
    • New options: auth, cluster, cluster_command_timeout, cluster_relay_context, sentinel, dbindex, failover and ssl.
    • class and persistent_id default to null, and lazy defaults to null, which are Symfony's defaults.
  • Memcached:

    • The connection option defaults now match the ones Symfony uses: connect_timeout 4000, poll_timeout 5000, retry_timeout 2, server_failure_limit 5 and tcp_nodelay true.
    • distribution, hash, compression_type and socket_recv_size are only set when configured. Previously distribution and hash were always set, which overrode libketama_compatible.
    • compression_type is now a \Memcached::COMPRESSION_* constant instead of a string.
    • dsn can be an array of DSNs.
    • New options: binary_protocol, persistent_id, username and password.
    • The undocumented socket_send_size option was never used and is not supported.
  • PDO:

    • db_data_col now defaults to item_data. It previously defaulted to item_id.
    • db_username and db_password default to null.
    • A Doctrine DBAL connection is no longer supported by the PDO adapter. Use a \PDO service or a PDO DSN, or the Doctrine DBAL adapter.
  • Proxy:

    • psr6Service is now pool, a wrapped cache config: 'psr6Service' => 'name' becomes 'pool' => ['service' => 'name']. See Wrapped Caches.
    • The documented maxLifetime option was never used. Use defaultLifetime.
  • Chain:

    • adapters is now a list of wrapped cache configs: 'adapters' => ['a', 'b'] becomes 'adapters' => [['service' => 'a'], ['service' => 'b']]. See Wrapped Caches.
    • The documented namespace option was never used and is not supported.
  • PHP Array:

    • backupCache is now a wrapped cache config: 'backupCache' => 'name' becomes 'backupCache' => ['service' => 'name']. See Wrapped Caches.
  • Services pulled from the container are now checked. A client, wrapped cache service, marshaller or logger service of the wrong type throws an InvalidConfigException.

  • Calling getContainer() on a container aware factory before a container has been set now throws a MissingServiceException instead of a TypeError.

New features

  • A logger service can be set on each cache. See Logger.
  • A marshaller service can be set on the APCu, Doctrine DBAL, Filesystem, Filesystem Tag Aware, Memcached, PDO, Redis and Redis Tag Aware adapters, and marshallers can be built with the new MarshallerFactory. See Marshallers.
  • The PHP Files adapter has an appendOnly option.
  • The Redis adapter accepts Relay clients.
  • SimpleCacheFactory builds a cache as a PSR-16 simple cache. See PSR-16 Simple Cache.
  • Wrapping adapters (Chain, PHP Array, Proxy and the new ones below) can build the caches they wrap from config, by type or by the name of another cache. See Wrapped Caches.
  • New adapters: Doctrine DBAL, Filesystem Tag Aware, Null, PSR-16, Redis Tag Aware, Tag Aware, Traceable and Traceable Tag Aware.

These docs, including the code samples, are licensed under a Creative Commons BY-SA 3.0 license.