跳到内容

缓存项

编辑此页

缓存项是以键/值对形式存储在缓存中的信息单元。在 Cache 组件中,它们由 CacheItem 类表示。它们在 Cache Contracts 和 PSR-6 接口中均有使用。

缓存项键和值

缓存项的是一个纯字符串,作为其标识符,因此对于每个缓存池都必须是唯一的。您可以自由选择键,但它们应仅包含字母 (A-Z, a-z)、数字 (0-9) 以及 _. 符号。其他常用符号(例如 { } ( ) / \ @ :)由 PSR-6 标准保留供将来使用。

缓存项的可以是 PHP 可序列化的任何类型表示的数据,例如基本类型(字符串、整数、浮点数、布尔值、null)、数组和对象。

创建缓存项

创建缓存项的唯一方法是通过缓存池。当使用 Cache Contracts 时,它们作为参数传递给重新计算回调

1
2
3
4
// $cache pool object was created before
$productsCount = $cache->get('stats.products_count', function (ItemInterface $item): string {
    // [...]
});

当使用 PSR-6 时,它们通过缓存池的 getItem($key) 方法创建

1
2
// $cache pool object was created before
$productsCount = $cache->getItem('stats.products_count');

然后,使用 Psr\Cache\CacheItemInterface::set 方法来设置存储在缓存项中的数据(当使用 Cache Contracts 时,此步骤会自动完成)

1
2
3
4
5
6
7
8
9
10
// storing a simple integer
$productsCount->set(4711);
$cache->save($productsCount);

// storing an array
$productsCount->set([
    'category1' => 4711,
    'category2' => 2387,
]);
$cache->save($productsCount);

任何给定缓存项的键和值都可以通过相应的 getter 方法获得

1
2
3
4
$cacheItem = $cache->getItem('exchange_rate');
// ...
$key = $cacheItem->getKey();
$value = $cacheItem->get();

缓存项过期

默认情况下,缓存项是永久存储的。实际上,这种“永久存储”可能会因所使用的缓存类型而异,如 缓存池和支持的适配器 文章中所述。

但是,在某些应用中,使用寿命较短的缓存项是很常见的。例如,考虑一个仅缓存最新新闻一分钟的应用。在这些情况下,使用 expiresAfter() 方法设置缓存项的秒数

1
2
3
4
$latestNews->expiresAfter(60);  // 60 seconds = 1 minute

// this method also accepts \DateInterval instances
$latestNews->expiresAfter(DateInterval::createFromDateString('1 hour'));

缓存项定义了另一个相关方法 expiresAt(),用于设置项过期的确切日期和时间

1
$mostPopularNews->expiresAt(new \DateTime('tomorrow'));

缓存项命中和未命中

使用缓存机制对于提高应用程序性能非常重要,但不应是使应用程序工作的必要条件。实际上,PSR-6 文档明智地指出,缓存错误不应导致应用程序失败。

在 PSR-6 的实践中,这意味着即使缓存项不存在,getItem() 方法始终返回一个实现 Psr\Cache\CacheItemInterface 接口的对象。因此,您不必处理 null 返回值,并且可以安全地在缓存中存储诸如 falsenull 之类的值。

为了确定返回的对象是否表示来自存储的值,缓存使用命中和未命中的概念

  • 缓存命中发生在请求的项在缓存中找到、其值未损坏或无效且未过期时;
  • 缓存未命中与命中相反,因此当在缓存中未找到该项、其值因任何原因损坏或无效或该项已过期时,就会发生缓存未命中。

缓存项对象定义了一个布尔值 isHit() 方法,对于缓存命中返回 true

1
2
3
4
5
6
7
8
9
$latestNews = $cache->getItem('latest_news');

if (!$latestNews->isHit()) {
    // do some heavy computation
    $news = ...;
    $cache->save($latestNews->set($news));
} else {
    $news = $latestNews->get();
}
本作品,包括代码示例,根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本