docs/en/cache.md
hyperf/cache provides aspect cache based on Aspect implementation, and also provides cache classes that implement Psr\SimpleCache\CacheInterface.
composer require hyperf/cache
| Configuration | Default value | Remark |
|---|---|---|
| driver | Hyperf\Cache\Driver\RedisDriver | Cache driver, default is Redis |
| packer | Hyperf\Codec\Packer\PhpSerializerPacker | Packager |
| prefix | c: | Cache prefix |
| skip_cache_results | [] | Certain results are not cached |
<?php
return [
'default' => [
'driver' => Hyperf\Cache\Driver\RedisDriver::class,
'packer' => Hyperf\Codec\Packer\PhpSerializerPacker::class,
'prefix' => 'c:',
'skip_cache_results' => [],
],
];
Simple Cache is the PSR-16 specification. This component adapts to the specification. If you want to use Psr\SimpleCache\CacheInterface Cache class, for example, if you want to rewrite the cache module of EasyWeChat, you can get Psr\SimpleCache\CacheInterface directly from the dependency injection container, as shown below:
$cache = $container->get(\Psr\SimpleCache\CacheInterface::class);
The component provides Hyperf\Cache\Annotation\Cacheable annotation, which acts on class methods and can configure the corresponding cache prefix, expiration time, listener and cache group.
For example, UserService provides a user method that can query user information corresponding to id. When the Hyperf\Cache\Annotation\Cacheable annotation is added, the corresponding Redis cache will be automatically generated. The key value is user:id and the timeout is 9000 seconds. When querying for the first time, it will be checked from the database, and for subsequent queries, it will be checked from the cache.
<?php
namespace App\Services;
use App\Models\User;
use Hyperf\Cache\Annotation\Cacheable;
class UserService
{
#[Cacheable(prefix: "user", ttl: 9000, listener: "user-update")]
public function user($id)
{
$user = User::query()->where('id',$id)->first();
if($user){
return $user->toArray();
}
return null;
}
}
#[Cacheable]We provide two annotations, CachePut and CacheEvict, to implement cache update and cache clearing operations.
Of course, we can also delete the cache through events. Let's create a new Service to provide a method to help us handle caching.
However, we recommend users to use annotation processing instead of listeners.
<?php
declare(strict_types=1);
namespace App\Service;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Cache\Listener\DeleteListenerEvent;
use Psr\EventDispatcher\EventDispatcherInterface;
class SystemService
{
#[Inject]
protected EventDispatcherInterface $dispatcher;
public function flushCache($userId)
{
$this->dispatcher->dispatch(new DeleteListenerEvent('user-update', [$userId]));
return true;
}
}
When we customize the value of Cacheable, such as the following situation.
<?php
declare(strict_types=1);
namespace App\Service\Cache;
use Hyperf\Cache\Annotation\Cacheable;
class DemoService
{
#[Cacheable(prefix: "cache", value: "_#{id}", listener: "user-update")]
public function getCache(int $id)
{
return $id . '_' . uniqid();
}
}
You need to modify the $arguments variable in the DeleteListenerEvent constructor accordingly. The specific code is as follows.
<?php
declare(strict_types=1);
namespace App\Service;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Cache\Listener\DeleteListenerEvent;
use Psr\EventDispatcher\EventDispatcherInterface;
class SystemService
{
#[Inject]
protected EventDispatcherInterface $dispatcher;
public function flushCache($userId)
{
$this->dispatcher->dispatch(new DeleteListenerEvent('user-update', ['id' => $userId]));
return true;
}
}
For example, in the following configuration, the cache prefix is user, the timeout is 7200, and the deletion event name is USER_CACHE. The corresponding cache KEY is generated as c:user:1.
<?php
declare(strict_types=1);
namespace App\Service;
use App\Models\User;
use Hyperf\Cache\Annotation\Cacheable;
class UserService
{
#[Cacheable(prefix: "user", ttl: 7200, listener: "USER_CACHE")]
public function user(int $id): array
{
$user = User::query()->find($id);
return [
'user' => $user->toArray(),
'uuid' => $this->unique(),
];
}
}
When value is set, the framework will cache the KEY key naming according to the set rules. In the following example, when $user->id = 1, the cached KEY is c:userBook:_1
This configuration also supports other types of cache annotations described below
<?php
declare(strict_types=1);
namespace App\Service;
use App\Models\User;
use Hyperf\Cache\Annotation\Cacheable;
class UserBookService
{
#[Cacheable(prefix: "userBook", ttl: 6666, value: "_#{user.id}")]
public function userBook(User $user): array
{
return [
'book' => $user->book->toArray(),
'uuid' => $this->unique(),
];
}
}
For example, in the following configuration, the cache prefix is user, the timeout is 7200, the corresponding cache KEY generated is c:user:1, and the cache is initialized every 10 seconds from 7200 to 600 seconds until the first time success.
<?php
declare(strict_types=1);
namespace App\Service;
use App\Models\User;
use Hyperf\Cache\Annotation\CacheAhead;
class UserService
{
#[CacheAhead(prefix: "user", ttl: 7200, aheadSeconds: 600, lockSeconds: 10)]
public function user(int $id): array
{
$user = User::query()->find($id);
return [
'user' => $user->toArray(),
'uuid' => $this->unique(),
];
}
}
CachePut is different from Cacheable in that it executes the function body every time it is called and then rewrites the cache. So when we want to update the cache, we can call the relevant methods.
<?php
declare(strict_types=1);
namespace App\Service;
use App\Models\User;
use Hyperf\Cache\Annotation\CachePut;
class UserService
{
#[CachePut(prefix: "user", ttl: 3601)]
public function updateUser(int $id)
{
$user = User::query()->find($id);
$user->name = 'HyperfDoc';
$user->save();
return [
'user' => $user->toArray(),
'uuid' => $this->unique(),
];
}
}
CacheEvict is easier to understand. When the method body is executed, the cache will be actively cleaned.
<?php
declare(strict_types=1);
namespace App\Service;
use Hyperf\Cache\Annotation\CacheEvict;
class UserBookService
{
#[CacheEvict(prefix: "userBook", value: "_#{id}")]
public function updateUserBook(int $id)
{
return true;
}
}
Hyperf\Cache\Driver\RedisDriver will store cache data in Redis, and users need to configure the corresponding Redis configuration. This mode is the default mode.
If you need to cache data into memory, you can try this driver. The configuration is as follows:
<?php
return [
'memory' => [
'driver' => Hyperf\Cache\Driver\MemoryDriver::class,
],
];
If you need to cache data into Context, you can try this driver. For example, in the following application scenario, Demo::get will be called multiple times in multiple places, but you do not want to query Redis every time.
<?php
use Hyperf\Cache\Annotation\Cacheable;
class Demo
{
public function get($userId, $id)
{
return $this->getArray($userId)[$id] ?? 0;
}
#[Cacheable(prefix: "test", group: "co")]
public function getArray(int $userId): array
{
return $this->redis->hGetAll($userId);
}
}
The corresponding configuration is as follows:
<?php
return [
'co' => [
'driver' => Hyperf\Cache\Driver\CoroutineMemoryDriver::class,
'packer' => Hyperf\Codec\Packer\PhpSerializerPacker::class,
],
];