Идёт обновление сайта. Несколько дней возможны сбои в оформлении и переводах. Документация работает — если страница выглядит сломанной, обновите её позже.

Документация
L Laravel L intervention/image
Войти

Кэш

10.x 7 мар 2026 г.

#Введение

Некоторые задачи по получению или обработке данных в вашем приложении могут быть ресурсоёмкими для процессора или занимать несколько секунд. В таких случаях обычно данные кэшируются на некоторое время, чтобы при повторных запросах к тем же данным их можно было получить быстрее. Кэшированные данные обычно хранятся в очень быстром хранилище, таком как Memcached или Redis.

К счастью, Laravel предоставляет выразительный и единый API для различных кэш-бэкендов, позволяя использовать их высокую скорость получения данных и ускорять работу вашего веб-приложения.

#Настройка

Файл конфигурации кэша вашего приложения находится в config/cache.php. В этом файле вы можете указать, какой драйвер кэша будет использоваться по умолчанию во всём приложении. Laravel из коробки поддерживает популярные кэш-бэкенды, такие как Memcached, Redis, DynamoDB и реляционные базы данных. Кроме того, доступен файловый драйвер кэша, а драйверы array и "null" предоставляют удобные варианты кэша для автоматизированных тестов.

Файл конфигурации кэша также содержит различные другие параметры, которые документированы внутри файла, поэтому обязательно ознакомьтесь с ними. По умолчанию Laravel настроен на использование драйвера file, который сохраняет сериализованные объекты кэша в файловой системе сервера. Для крупных приложений рекомендуется использовать более надёжные драйверы, такие как Memcached или Redis. Вы также можете настроить несколько конфигураций кэша для одного и того же драйвера.

#Требования к драйверу

#Database

При использовании драйвера кэша database необходимо создать таблицу для хранения элементов кэша. Ниже приведён пример объявления схемы Schema для такой таблицы:

Schema::create('cache', function (Blueprint $table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});
Примечание

Вы также можете использовать Artisan-команду php artisan cache:table для генерации миграции с правильной схемой.

#Memcached

Для использования драйвера Memcached необходимо установить PECL-пакет Memcached. Все ваши серверы Memcached можно перечислить в файле конфигурации config/cache.php. В этом файле уже есть запись memcached.servers для начала работы:

'memcached' => [
    'servers' => [
        [
            'host' => env('MEMCACHED_HOST', '127.0.0.1'),
            'port' => env('MEMCACHED_PORT', 11211),
            'weight' => 100,
        ],
    ],
],

При необходимости вы можете указать опцию host как путь к UNIX-сокету. В этом случае опция port должна быть установлена в 0:

'memcached' => [
    [
        'host' => '/var/run/memcached/memcached.sock',
        'port' => 0,
        'weight' => 100
    ],
],

#Redis

Перед использованием Redis в Laravel необходимо либо установить расширение PhpRedis через PECL, либо установить пакет predis/predis (~1.0) через Composer. Laravel Sail уже включает это расширение. Кроме того, официальные платформы развертывания Laravel, такие как Laravel Forge и Laravel Vapor, по умолчанию имеют установленное расширение PhpRedis.

Для получения дополнительной информации о настройке Redis обратитесь к его странице документации Laravel.

#DynamoDB

Перед использованием драйвера кэша DynamoDB необходимо создать таблицу DynamoDB для хранения всех кэшированных данных. Обычно эта таблица должна называться cache. Однако имя таблицы следует задавать в соответствии со значением параметра stores.dynamodb.table в конфигурации cache вашего приложения.

Эта таблица также должна иметь строковой ключ раздела с именем, соответствующим значению параметра stores.dynamodb.attributes.key в конфигурации cache вашего приложения. По умолчанию ключ раздела должен называться key.

#Использование кэша

#Получение экземпляра кэша

Для получения экземпляра хранилища кэша вы можете использовать фасад Cache, который будет использоваться в этой документации. Фасад Cache предоставляет удобный и лаконичный доступ к внутренним реализациям контрактов кэша Laravel:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Показать список всех пользователей приложения.
     */
    public function index(): array
    {
        $value = Cache::get('key');

        return [
            // ...
        ];
    }
}

#Доступ к нескольким хранилищам кэша

Используя фасад Cache, вы можете получить доступ к разным хранилищам кэша через метод store. Ключ, передаваемый в метод store, должен соответствовать одному из хранилищ, перечисленных в массиве stores в файле конфигурации cache:

$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar', 'baz', 600); // 10 минут

#Получение элементов из кэша

Метод get фасада Cache используется для получения элементов из кэша. Если элемент отсутствует в кэше, будет возвращено null. При желании вы можете передать вторым аргументом методу get значение по умолчанию, которое будет возвращено, если элемент не существует:

$value = Cache::get('key');

$value = Cache::get('key', 'default');

Вы также можете передать замыкание в качестве значения по умолчанию. Результат выполнения замыкания будет возвращён, если указанный элемент отсутствует в кэше. Это позволяет отложить получение значений по умолчанию из базы данных или другого внешнего сервиса:

$value = Cache::get('key', function () {
    return DB::table(/* ... */)->get();
});

#Проверка существования элемента

Метод has позволяет проверить, существует ли элемент в кэше. Этот метод также вернёт false, если элемент существует, но его значение равно null:

if (Cache::has('key')) {
    // ...
}

#Увеличение / уменьшение значений

Методы increment и decrement позволяют изменять значение целочисленных элементов в кэше. Оба метода принимают необязательный второй аргумент — величину, на которую нужно увеличить или уменьшить значение:

// Инициализировать значение, если оно отсутствует...
Cache::add('key', 0, now()->addHours(4));

// Увеличить или уменьшить значение...
Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);

#Получить и сохранить

Иногда нужно получить элемент из кэша, а если он отсутствует — сохранить значение по умолчанию. Например, можно получить всех пользователей из кэша или, если их там нет, загрузить из базы и добавить в кэш. Для этого используется метод Cache::remember:

$value = Cache::remember('users', $seconds, function () {
    return DB::table('users')->get();
});

Если элемент отсутствует в кэше, замыкание, переданное методу remember, будет выполнено, и его результат будет помещён в кэш.

Метод rememberForever позволяет получить элемент из кэша или сохранить его навсегда, если он отсутствует:

$value = Cache::rememberForever('users', function () {
    return DB::table('users')->get();
});

#Получить и удалить

Если нужно получить элемент из кэша и сразу удалить его, используйте метод pull. Как и метод get, он вернёт null, если элемент отсутствует:

$value = Cache::pull('key');

#Сохранение элементов в кэш

Для сохранения элементов в кэш используйте метод put фасада Cache:

Cache::put('key', 'value', $seconds = 10);

Если время хранения не передано в метод put, элемент будет храниться бессрочно:

Cache::put('key', 'value');

Вместо передачи количества секунд в виде целого числа, можно передать объект DateTime, указывающий время истечения срока действия кэшированного элемента:

Cache::put('key', 'value', now()->addMinutes(10));

#Сохранить, если отсутствует

Метод add добавит элемент в кэш только если его там ещё нет. Метод вернёт true, если элемент был добавлен, и false в противном случае. Операция add является атомарной:

Cache::add('key', 'value', $seconds);

#Сохранение элементов навсегда

Метод forever позволяет сохранить элемент в кэше навсегда. Поскольку такие элементы не истекают, их нужно удалять вручную с помощью метода forget:

Cache::forever('key', 'value');
Примечание

Если вы используете драйвер Memcached, элементы, сохранённые "навсегда", могут быть удалены при достижении лимита размера кэша.

#Удаление элементов из кэша

Для удаления элементов из кэша используйте метод forget:

Cache::forget('key');

Также можно удалить элементы, указав время хранения в секундах равным нулю или отрицательному числу:

Cache::put('key', 'value', 0);

Cache::put('key', 'value', -5);

Для очистки всего кэша используйте метод flush:

Cache::flush();
Внимание

Очистка кэша игнорирует настроенный вами префикс кэша "prefix" и удалит все записи из кэша. Учитывайте это при очистке кэша, который используется совместно с другими приложениями.

#Хелпер Cache

Помимо фасада Cache, вы можете использовать глобальную функцию cache для получения и сохранения данных в кэше. Если вызвать функцию cache с одним строковым аргументом, она вернёт значение по ключу:

$value = cache('key');

Если передать массив пар ключ/значение и время хранения, функция сохранит значения в кэше на указанное время:

cache(['key' => 'value'], $seconds);

cache(['key' => 'value'], now()->addMinutes(10));

Если вызвать функцию cache без аргументов, она вернёт экземпляр реализации Illuminate\Contracts\Cache\Factory, позволяя вызывать другие методы кэширования:

cache()->remember('users', $seconds, function () {
    return DB::table('users')->get();
});
Примечание

При тестировании вызовов глобальной функции cache вы можете использовать метод Cache::shouldReceive так же, как при тестировании фасада.

#Атомарные блокировки

Внимание

Для использования этой функции ваше приложение должно использовать один из драйверов кэша memcached, redis, dynamodb, database, file или array в качестве драйвера кэша по умолчанию. Кроме того, все серверы должны работать с одним и тем же центральным сервером кэша.

#Требования к драйверу

#Database

При использовании драйвера кэша database необходимо создать таблицу для хранения блокировок кэша вашего приложения. Ниже приведён пример объявления схемы Schema для такой таблицы:

Schema::create('cache_locks', function (Blueprint $table) {
    $table->string('key')->primary();
    $table->string('owner');
    $table->integer('expiration');
});
Примечание

Если вы использовали Artisan-команду cache:table для создания таблицы кэша драйвера базы данных, миграция, созданная этой командой, уже содержит определение таблицы cache_locks.

#Управление блокировками

Атомарные блокировки позволяют управлять распределёнными блокировками без риска гонок. Например, Laravel Forge использует атомарные блокировки, чтобы гарантировать выполнение только одной удалённой задачи на сервере одновременно. Вы можете создавать и управлять блокировками с помощью метода Cache::lock:

use Illuminate\Support\Facades\Cache;

$lock = Cache::lock('foo', 10);

if ($lock->get()) {
    // Блокировка получена на 10 секунд...

    $lock->release();
}

Метод get также принимает замыкание. После выполнения замыкания Laravel автоматически снимет блокировку:

Cache::lock('foo', 10)->get(function () {
    // Блокировка получена на 10 секунд и автоматически снята...
});

Если блокировка недоступна в момент запроса, вы можете указать Laravel ждать заданное количество секунд. Если блокировку не удастся получить за это время, будет выброшено исключение Illuminate\Contracts\Cache\LockTimeoutException:

use Illuminate\Contracts\Cache\LockTimeoutException;

$lock = Cache::lock('foo', 10);

try {
    $lock->block(5);

    // Блокировка получена после ожидания максимум 5 секунд...
} catch (LockTimeoutException $e) {
    // Не удалось получить блокировку...
} finally {
    $lock?->release();
}

Пример выше можно упростить, передав замыкание в метод block. В этом случае Laravel попытается получить блокировку в течение указанного времени и автоматически снимет её после выполнения замыкания:

Cache::lock('foo', 10)->block(5, function () {
    // Блокировка получена после ожидания максимум 5 секунд...
});

#Управление блокировками между процессами

Иногда нужно получить блокировку в одном процессе и снять её в другом. Например, можно получить блокировку во время веб-запроса и снять её в конце очередной задачи, вызванной этим запросом. В таком случае следует передать токен владельца блокировки в очередь, чтобы задача могла восстановить блокировку по этому токену.

В примере ниже мы отправляем задачу в очередь, если блокировка успешно получена. Также мы передаём токен владельца блокировки в задачу через метод owner блокировки:

$podcast = Podcast::find($id);

$lock = Cache::lock('processing', 120);

if ($lock->get()) {
    ProcessPodcast::dispatch($podcast, $lock->owner());
}

В задаче ProcessPodcast нашего приложения мы можем восстановить и снять блокировку, используя токен владельца:

Cache::restoreLock('processing', $this->owner)->release();

Если нужно снять блокировку без учёта текущего владельца, используйте метод forceRelease:

Cache::lock('processing')->forceRelease();

#Добавление пользовательских драйверов кэша

#Создание драйвера

Для создания собственного драйвера кэша сначала необходимо реализовать контракт Illuminate\Contracts\Cache\Store contract. Например, реализация кэша для MongoDB может выглядеть так:

<?php

namespace App\Extensions;

use Illuminate\Contracts\Cache\Store;

class MongoStore implements Store
{
    public function get($key) {}
    public function many(array $keys) {}
    public function put($key, $value, $seconds) {}
    public function putMany(array $values, $seconds) {}
    public function increment($key, $value = 1) {}
    public function decrement($key, $value = 1) {}
    public function forever($key, $value) {}
    public function forget($key) {}
    public function flush() {}
    public function getPrefix() {}
}

Осталось реализовать каждый из этих методов, используя соединение с MongoDB. Для примера реализации посмотрите класс Illuminate\Cache\MemcachedStore в исходном коде Laravel. После завершения реализации можно зарегистрировать пользовательский драйвер, вызвав метод extend фасада Cache:

Cache::extend('mongo', function (Application $app) {
    return Cache::repository(new MongoStore);
});
Примечание

Если вы не знаете, куда поместить код пользовательского драйвера кэша, можно создать пространство имён Extensions внутри каталога app. Однако помните, что Laravel не навязывает жёсткую структуру приложения, и вы можете организовать его по своему усмотрению.

#Регистрация драйвера

Чтобы зарегистрировать пользовательский драйвер кэша в Laravel, мы используем метод extend фасада Cache. Поскольку другие сервис-провайдеры могут попытаться прочитать кэшированные значения в своём методе boot, мы зарегистрируем наш драйвер внутри booting-обратного вызова. Используя booting, мы гарантируем, что пользовательский драйвер будет зарегистрирован сразу до вызова boot у сервис-провайдеров приложения, но после вызова register у всех провайдеров. Мы зарегистрируем наш booting-обратный вызов в методе register класса App\Providers\AppServiceProvider приложения:

<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Регистрация сервисов приложения.
     */
    public function register(): void
    {
        $this->app->booting(function () {
             Cache::extend('mongo', function (Application $app) {
                 return Cache::repository(new MongoStore);
             });
         });
    }

    /**
     * Загрузка сервисов приложения.
     */
    public function boot(): void
    {
        // ...
    }
}

Первый аргумент метода extend — имя драйвера. Оно должно совпадать с опцией driver в файле конфигурации config/cache.php. Второй аргумент — замыкание, которое должно возвращать экземпляр Illuminate\Cache\Repository. В замыкание передаётся $app — экземпляр контейнера сервисов.

После регистрации расширения обновите опцию driver в файле конфигурации config/cache.php, указав имя вашего расширения.

#События

Чтобы выполнять код при каждой операции с кэшем, вы можете слушать события, генерируемые кэшем. Обычно слушатели событий размещают в классе App\Providers\EventServiceProvider вашего приложения:

use App\Listeners\LogCacheHit;
use App\Listeners\LogCacheMissed;
use App\Listeners\LogKeyForgotten;
use App\Listeners\LogKeyWritten;
use Illuminate\Cache\Events\CacheHit;
use Illuminate\Cache\Events\CacheMissed;
use Illuminate\Cache\Events\KeyForgotten;
use Illuminate\Cache\Events\KeyWritten;

/**
 * Отображение слушателей событий для приложения.
 *
 * @var array
 */
protected $listen = [
    CacheHit::class => [
        LogCacheHit::class,
    ],

    CacheMissed::class => [
        LogCacheMissed::class,
    ],

    KeyForgotten::class => [
        LogKeyForgotten::class,
    ],

    KeyWritten::class => [
        LogKeyWritten::class,
    ],
];