Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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

CallWhat 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-all

The 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().

Thanks for reading!

Donate to the site — we work hard for you.