Конфигурация

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

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

 

Необходимые условия для водителя

База данных

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

Schema::create('cache', function ($table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});

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

Memcached

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

'memcached' => [
    [
        'host' => '127.0.0.1',
        'port' => 11211,
        'weight' => 100
    ],
],

Вы также можете установить hostопцию для пути к сокету UNIX. Если вы сделаете это, portопция должна быть установлена ​​на 0:

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

Redis

Перед использованием кэша Redis с Laravel вам нужно будет либо установить пакет (~ 1.0) через Composer, либо установить расширение PhpRedis PHP через PECL.predis/predis

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

 

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

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

И контракты обеспечивают доступ к услугам кэшей Laravel в. Контракт обеспечивает доступ ко всем водителям кэша , определенными для вашего приложения. Контракт , как правило , реализация драйвера кэша по умолчанию для вашего приложения , как указано на вашем конфигурационном файле.Illuminate\Contracts\Cache\FactoryIlluminate\Contracts\Cache\RepositoryFactoryRepositorycache

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

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Show a list of all users of the application.
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}

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

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

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

Cache::store('redis')->put('bar', 'baz', 600); // 10 Minutes

 

Извлечение предметов из кеша

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

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

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

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

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

Проверка наличия товара

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

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

Увеличение / Уменьшение Ценности

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

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();
});

Если элемент не существует в кеше, Closureпереданный 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);

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

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

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

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

Магазин, если не присутствует

addМетод будет только добавить элемент в кэш , если он уже не существует в хранилище кэша. Метод вернется, trueесли элемент фактически добавлен в кэш. В противном случае метод вернет false:

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

Хранение предметов навсегда

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

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

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

 

Извлечение элементов из кэша

Вы можете удалить элементы из кэша, используя forgetметод:

Cache::forget('key');

Вы также можете удалить элементы, указав нулевой или отрицательный TTL:

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

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

Вы можете очистить весь кеш, используя flushметод:

Cache::flush();

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

 

Атомные Замки

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

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

use Illuminate\Support\Facades\Cache;

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

if ($lock->get()) {
    // Lock acquired for 10 seconds...

    $lock->release();
}

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

Cache::lock('foo')->get(function () {
    // Lock acquired indefinitely and automatically released...
});

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

use Illuminate\Contracts\Cache\LockTimeoutException;

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

try {
    $lock->block(5);

    // Lock acquired after waiting maximum of 5 seconds...
} catch (LockTimeoutException $e) {
    // Unable to acquire lock...
} finally {
    optional($lock)->release();
}

Cache::lock('foo', 10)->block(5, function () {
    // Lock acquired after waiting maximum of 5 seconds...
});

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

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

// Within Controller...
$podcast = Podcast::find($id);

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

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

// Within ProcessPodcast Job...
Cache::restoreLock('foo', $this->owner)->release();

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

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

 

Помощник кеша

Помимо использования 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

 

Теги кеша

Теги кеша не поддерживаются при использовании драйверов кеша fileили database. Кроме того, при использовании нескольких тегов с кэшами, которые хранятся «навсегда», производительность будет наилучшей с драйвером, таким как memcached, который автоматически удаляет устаревшие записи.

 

Хранение помеченных элементов кэша

Кэшированные теги позволяют помечать связанные элементы в кэше, а затем сбрасывать все кэшированные значения, которым был присвоен данный тег. Вы можете получить доступ к тегу кеша, передав упорядоченный массив имен тегов. Например, давайте перейдем к помеченному кешу и putзначению в кеше:

Cache::tags(['people', 'artists'])->put('John', $john, $seconds);

Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);

 

Доступ к тегированным элементам кэша

Чтобы получить помеченный элемент кэша, передайте tagsметоду тот же упорядоченный список тегов, а затем вызовите getметод с ключом, который вы хотите получить:

$john = Cache::tags(['people', 'artists'])->get('John');

$anne = Cache::tags(['people', 'authors'])->get('Anne');

 

Удаление помеченных элементов кэша

Вы можете сбросить все элементы, которым назначен тег или список тегов. Например, это утверждение было бы удалить все кэша с меткой либо peopleauthorsили оба. Итак, оба Anneи Johnбудут удалены из кеша:

Cache::tags(['people', 'authors'])->flush();

Напротив, это утверждение удалит только кэши с тегами authors, поэтому Anneбудет удалено, но не John:

Cache::tags('authors')->flush();

 

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

Написание драйвера

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

<?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

Cache::extend('mongo', function ($app) {
    return Cache::repository(new MongoStore);
});

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

 

Регистрация водителя

Чтобы зарегистрировать пользовательский драйвер кэша в Laravel, мы будем использовать extendметод на Cacheфасаде. Вызов может быть выполнен методом по умолчанию, который поставляется со свежими приложениями Laravel, или вы можете создать своего собственного поставщика услуг для размещения расширения - просто не забудьте зарегистрировать поставщика в массиве провайдеров:Cache::extendbootApp\Providers\AppServiceProviderconfig/app.php

<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('mongo', function ($app) {
            return Cache::repository(new MongoStore);
        });
    }
}

Первым аргументом, передаваемым extendметоду, является имя драйвера. Это будет соответствовать вашему driverварианту в файле конфигурации. Второй аргумент - это Closure, который должен возвращать экземпляр. Закрытию будет передан экземпляр, который является экземпляром сервисного контейнера .config/cache.phpIlluminate\Cache\Repository$app

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

 

События

Чтобы выполнить код для каждой операции кеширования, вы можете прослушивать события,запускаемые кешем. Как правило, вы должны размещать эти слушатели событий в вашем EventServiceProvider:

/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Cache\Events\CacheHit' => [
        'App\Listeners\LogCacheHit',
    ],

    'Illuminate\Cache\Events\CacheMissed' => [
        'App\Listeners\LogCacheMissed',
    ],

    'Illuminate\Cache\Events\KeyForgotten' => [
        'App\Listeners\LogKeyForgotten',
    ],

    'Illuminate\Cache\Events\KeyWritten' => [
        'App\Listeners\LogKeyWritten',
    ],
];