Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Caching

A cache is temporary storage for ready results. If something takes long to compute or fetch from the database, the result is saved and later requests get it instantly. In Laminas the laminas-cache package does this, and the storage place — files, memory, Redis — is set by a separate adapter package.

Installation

composer require laminas/laminas-cache laminas/laminas-cache-storage-adapter-filesystem

The second package keeps the cache in files. Agree to inject the Laminas\Cache and Laminas\Cache\Storage\Adapter\Filesystem modules into config/modules.config.php.

Configuring a storage

Storages are described in the caches section of config/autoload/global.php:

// config/autoload/global.php
use Laminas\Cache\Storage\Adapter\Filesystem;
 
return [
    'caches' => [
        'BlogCache' => [
            'adapter' => Filesystem::class,
            'options' => [
                'cache_dir' => 'data/cache',
                'ttl' => 600,
            ],
        ],
    ],
];
KeyMeaning
BlogCacheThe service name under which the storage sits in the container
adapterWhere the data is kept
cache_dirThe folder for cache files (it exists in the skeleton)
ttlHow many seconds an entry is considered fresh

A service with a cache

Create a service that counts posts and remembers the result:

// module/Blog/src/Service/PostCounter.php
namespace Blog\Service;
 
use Blog\Model\PostTable;
use Laminas\Cache\Storage\StorageInterface;
 
class PostCounter
{
    public function __construct(
        private PostTable $posts,
        private StorageInterface $cache,
    ) {}
 
    public function count(): int
    {
        $cached = $this->cache->getItem('post_count');
 
        if ($cached !== null) {
            return (int) $cached;
        }
 
        $count = count($this->posts->fetchAll());
        $this->cache->setItem('post_count', (string) $count);
 
        return $count;
    }
}

getItem() returns null when the entry is missing or expired. Then the value is computed and saved with setItem().

The storage is named in the configuration by a string, not a class, so the factory is written by hand:

// module/Blog/src/Service/PostCounterFactory.php
public function __invoke(ContainerInterface $container): PostCounter
{
    return new PostCounter(
        $container->get(PostTable::class),
        $container->get('BlogCache'),
    );
}

Register PostCounter with this factory in service_manager and pass the service to the controller. The first call of $this->postCounter->count() runs the query, and for the next ten minutes the number comes from a file in data/cache.

Clearing the cache

When the data changes, the entry is removed so that a stale number is not shown:

public function reset(): void
{
    $this->cache->removeItem('post_count');
}

Call reset() after a post is added or deleted.

Storage methods

MethodWhat it does
getItem($key)Reads an entry or returns null
setItem($key, $value)Saves an entry
hasItem($key)Checks whether a fresh entry exists
removeItem($key)Removes an entry

The filesystem adapter stores strings. To cache arrays, turn the value into a string with json_encode() and back with json_decode(), or attach the serializer plugin from the laminas-serializer package to the storage.

Common mistake

A cache that is not cleared when the data changes shows old values until ttl runs out: a post is added, but the counter is the same. For every cache entry decide in advance which action makes it stale, and call removeItem() there.

Thanks for reading!

Donate to the site — we work hard for you.