存储在缓存中的每项数据都通过键作唯一识别。当你在缓存中存储一项数据时,必须为它指定一个键,稍后从缓存中取回数据时,也需要提供相应的键。
你可以使用一个字符串或者任意值作为一个缓存键。当键不是一个字符串时,它将会自动被序列化为一个字符串。
定义一个缓存键常见的一个策略就是在一个数组中包含所有的决定性因素。例如,yii\db\Schema 使用如下键存储一个数据表的结构信息。
[ __CLASS__, // 结构类名 $this->db->dsn, // 数据源名称 $this->db->username, // 数据库登录用户名 $name, // 表名 ];
如你所见,该键包含了可唯一指定一个数据库表所需的所有必要信息。
当同一个缓存存储器被用于多个不同的应用时,应该为每个应用指定一个唯一的缓存键前缀以避免缓存键冲突。可以通过配置 yii\caching\Cache::keyPrefix 属性实现。例如,在应用配置中可以编写如下代码:
'components' => [ 'cache' => [ 'class' => 'yii\caching\ApcCache', 'keyPrefix' => 'myapp', // 唯一键前缀 ], ],
为了确保互通性,此处只能使用字母和数字。
缓存过期
默认情况下,缓存中的数据会永久存留,除非它被某些缓存策略强制移除(例如:缓存空间已满,最老的数据会被移除)。要改变此特性,你可以在调用 yii\caching\Cache::set() 存储一项数据时提供一个过期时间参数。该参数代表这项数据在缓存中可保持有效多少秒。当你调用 yii\caching\Cache::get() 取回数据时,如果它已经过了超时时间,该方法将返回 false,表明在缓存中找不到这项数据。例如:
// 将数据在缓存中保留 45 秒 $cache->set($key, $data, 45); sleep(50); $data = $cache->get($key); if ($data === false) { // $data 已过期,或者在缓存中找不到 }
缓存依赖
除了超时设置,缓存数据还可能受到缓存依赖的影响而失效。例如,yii\caching\FileDependency 代表对一个文件修改时间的依赖。这个依赖条件发生变化也就意味着相应的文件已经被修改。因此,缓存中任何过期的文件内容都应该被置为失效状态,对 yii\caching\Cache::get() 的调用都应该返回 false。
缓存依赖用 yii\caching\Dependency 的派生类所表示。当调用 yii\caching\Cache::set() 在缓存中存储一项数据时,可以同时传递一个关联的缓存依赖对象。例如:
// 创建一个对 example.txt 文件修改时间的缓存依赖 $dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']); // 缓存数据将在30秒后超时 // 如果 example.txt 被修改,它也可能被更早地置为失效状态。 $cache->set($key, $data, 30, $dependency); // 缓存会检查数据是否已超时。 // 它还会检查关联的依赖是否已变化。 // 符合任何一个条件时都会返回 false。 $data = $cache->get($key);
下面是可用的缓存依赖的概况:
yii\caching\ChainedDependency:如果依赖链上任何一个依赖产生变化,则依赖改变。
yii\caching\DbDependency:如果指定 SQL 语句的查询结果发生了变化,则依赖改变。
yii\caching\ExpressionDependency:如果指定的 PHP 表达式执行结果发生变化,则依赖改变。
yii\caching\FileDependency:如果文件的最后修改时间发生变化,则依赖改变。
yii\caching\GroupDependency:将一项缓存数据标记到一个组名,你可以通过调用 yii\caching\GroupDependency::invalidate() 一次性将相同组名的缓存全部置为失效状态。
查询缓存
查询缓存是一个建立在数据缓存之上的特殊缓存特性。它用于缓存数据库查询的结果。
查询缓存需要一个 yii\db\Connection 和一个有效的 cache 应用组件。查询缓存的基本用法如下,假设 $db 是一个 yii\db\Connection 实例:
$duration = 60; // 缓存查询结果60秒 $dependency = ...; // 可选的缓存依赖 $db->beginCache($duration, $dependency); // ...这儿执行数据库查询... $db->endCache();
如你所见,beginCache() 和 endCache() 中间的任何查询结果都会被缓存起来。如果缓存中找到了同样查询的结果,则查询会被跳过,直接从缓存中提取结果。
查询缓存可以用于 ActiveRecord 和 DAO。