缓存项
缓存项是以键/值对形式存储在缓存中的信息单元。在 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
返回值,并且可以安全地在缓存中存储诸如 false
和 null
之类的值。
为了确定返回的对象是否表示来自存储的值,缓存使用命中和未命中的概念
- 缓存命中发生在请求的项在缓存中找到、其值未损坏或无效且未过期时;
- 缓存未命中与命中相反,因此当在缓存中未找到该项、其值因任何原因损坏或无效或该项已过期时,就会发生缓存未命中。
缓存项对象定义了一个布尔值 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();
}