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-filesystemThe 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,
],
],
],
];| Key | Meaning |
|---|---|
BlogCache | The service name under which the storage sits in the container |
adapter | Where the data is kept |
cache_dir | The folder for cache files (it exists in the skeleton) |
ttl | How 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
| Method | What 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.