Caching
A cache is a temporary storage for ready results. If the list of latest posts takes long to build, it is computed once, put into the cache and served from there for the next few minutes without touching the database.
Where the cache is configured
The cache is the cache component. It is already described in config/web.php:
// config/web.php
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
],FileCache stores data in files in the runtime/cache folder, and nothing extra has to be installed.
Writing and reading
// controllers/PostController.php
public function actionLatest(): string
{
$posts = Yii::$app->cache->getOrSet('latest-posts', function () {
return Post::find()->orderBy(['created_at' => SORT_DESC])->limit(5)->all();
}, 600);
return $this->render('index', ['posts' => $posts]);
}getOrSet() looks for a value with the key latest-posts in the cache. If there is none, it runs the function, stores the result for 600 seconds and returns it. The first opening of the page runs a database query, the next ten minutes do not; you can see it by the number of queries in the debug toolbar.
Cache methods
| Call | What it does |
|---|---|
$cache->set('key', $value, 600) | Stores a value for 600 seconds |
$cache->get('key') | Returns the value, or false if there is none |
$cache->getOrSet('key', $callable, 600) | Reads, and if missing calculates and stores |
$cache->delete('key') | Removes a value |
$cache->flush() | Clears the whole cache |
Resetting on change
An outdated cache entry is removed when the data changes. A convenient place is the model method Yii calls after every save:
// models/Post.php
public function afterSave($insert, $changedAttributes): void
{
parent::afterSave($insert, $changedAttributes);
Yii::$app->cache->delete('latest-posts');
}After a post is created or changed, the latest list is rebuilt the next time the page is opened.
Query cache
The result of a single database query is cached with the cache() method:
$posts = Post::find()->where(['status' => 1])->cache(60)->all();For a minute the same query returns the stored rows.
Caching a part of a view
The ready markup of a block can be stored too:
<?php
// views/layouts/main.php
?>
<?php if ($this->beginCache('sidebar', ['duration' => 300])): ?>
<aside>
<!-- a heavy block: a tag cloud, recent comments -->
</aside>
<?php $this->endCache(); ?>
<?php endif; ?>The first time the block runs and is stored; for the next five minutes Yii inserts the ready markup and does not run the code inside.
Clearing from the console
php yii cache/flush-allThe command clears all cache components described in config/console.php.
Other storages
On busy sites files are replaced with in-memory storage. Only the component class changes, and the code stays the same: yii\caching\MemCache for Memcached, yii\redis\Cache from the yiisoft/yii2-redis package for Redis.
Common mistake
The get() method returns false when there is no value. If you check the result with if (!$value), an empty array and zero are taken for a miss, and the cache never works. Compare strictly, if ($value === false), or use getOrSet().