Версія фреймворка: 8.x

Кеш

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

Laravel забезпечує виразний уніфікований API для різних кешуючих кеш-файлів. Конфігурація кешу знаходиться за адресоюconfig/cache.php. У цьому файлі ви можете вказати, який драйвер кешу ви хочете використовувати за замовчуванням у всій програмі. Laravel підтримує такі популярні кешування, якMemcached,Редіс, іДинамоДБз коробки. Laravel також підтримує APC, Array, Database, File таnullкеш драйвера.

Файл конфігурації кешу також містить різні інші параметри, які задокументовані у файлі, тому обов’язково прочитайте ці параметри. За замовчуванням Laravel налаштовано на використанняfileкеш-драйвер, який зберігає серіалізовані кешовані об’єкти у файловій системі. Для великих програм рекомендується використовувати більш надійний драйвер, такий як Memcached або Redis. Ви навіть можете налаштувати кілька конфігурацій кешу для одного драйвера.

Передумови драйвера

База даних

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

Schema::create('cache', function ($table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});
Ви також можете використовуватиphp artisan cache:tableКоманда Artisan для генерації міграції з відповідною схемою.

Memcached

Using the Memcached driver requires the Пакет 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 з Laravel, вам доведеться або встановити розширення PHpRedis PHP через PECL, або встановитиpredis/predisпакет (~ 1.0) через Composer.

Щоб отримати додаткову інформацію про налаштування Redis, перегляньте йогоСторінка документації Laravel.

Використання кешу

Отримання екземпляра кешу

Illuminate\Contracts\Cache\FactoryіIlluminate\Contracts\Cache\Repositoryконтрактинадати доступ до кеш-послуг Laravel.FactoryДоговір надає доступ до всіх драйверів кешу, визначених для вашої програми.RepositoryКонтракт, як правило, є реалізацією драйвера кешування за замовчуванням для Вашої програми, як вказано Вашимcacheфайл конфігурації.

Однак ви також можете використовуватиCacheфасад, що і будемо використовувати в цій документації.CacheFacadeзабезпечує зручний, стислий доступ до основних реалізацій контрактів кешування 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 method on the CacheFacadeвикористовується для отримання елементів з кешу. Якщо елемент не існує в кеші,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 methods may be used to adjust the value of integer items in the cache. Both of these methods accept an optional second argument indicating the amount by which to increment or decrement the item's value:

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');

Зберігання Objects у кеші

Ви можете використовуватиputметод наCacheFacadeдля зберігання Objects у кеші:

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

Якщо час зберігання не передано вputметод, предмет буде зберігатися необмежений час:

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

Замість того, щоб передавати кількість секунд як ціле число, ви також можете передати aDateTimeекземпляр, що представляє час закінчення кешованого елемента:

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

Зберігати, якщо немає

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

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

Зберігання Objects назавжди

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();
Очищення кеш-пам’яті не поважає префікс кеш-пам’яті та видалить усі записи з кешу. Розгляньте це уважно, очищаючи кеш-пам’ять, яким користуються інші програми.

Помічник кешу

На додаток до використанняCacheFacadeабодоговір кешування, Ви також можете використовувати глобальний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,dynamodb, абоdatabaseдрайвери кешу. Крім того, при використанні декількох тегів з кешами, які зберігаються "назавжди", продуктивність буде найкращою з таким драйвером, якmemcached, який автоматично видаляє застарілі записи.

Зберігання Tagged елементів кешу

Теги кеш-пам’яті дозволяють позначати пов’язані елементи в кеші, а потім очищати всі кешовані значення, яким було призначено даний тег. Ви можете отримати доступ до позначеного кешу, передавши впорядкований масив імен тегів. Наприклад, давайте отримаємо доступ до позначеного кешу таputзначення в кеші:

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

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

Доступ до Tagged елементів кешу

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

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

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

Видалення Tagged елементів кешу

Ви можете очистити всі елементи, яким призначено тег або список тегів. Наприклад, це твердження видалить усі кеші, позначені будь-якимpeople,authors, або обидва. Отже, обидваAnneіJohnбуде видалено з кешу:

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

На відміну від цього, це твердження видалить лише кеші, позначені тегомauthors, томуAnneбуде видалено, але ніJohn:

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

Atomic замки

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

Передумови драйвера

База даних

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

Schema::create('cache_locks', function ($table) {
    $table->string('key')->primary();
    $table->string('owner');
    $table->integer('expiration');
});

Управління Locks

Atomic замки дозволяють маніпулювати розподіленими Locks, не турбуючись про умови перегонів. Наприклад,Кузня Laravelвикористовує Atomic блокування, щоб гарантувати, що на сервері одночасно виконується лише одне віддалене завдання. Ви можете створювати та керувати Locks за допомогоюCache::lockметод:

use Illuminate\Support\Facades\Cache;

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

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

    $lock->release();
}

getметод також приймає Закриття. Після виконання Закриття Laravel автоматично відпустить Lock:

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

Якщо Lock недоступний на момент запиту, ви можете доручити Laravel почекати вказану кількість секунд. Якщо Lock не вдається отримати протягом зазначеного терміну, aIlluminate\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...
});

Управління Locks в різних процесах

Іноді, можливо, ви захочете отримати Lock в одному процесі та звільнити його в іншому процесі. Наприклад, ви можете отримати блокування під час веб-запиту і захочете звільнити блокування в кінці завдання, яке знаходиться в черзі, яке ініціюється цим запитом. У цьому сценарії ви повинні передати охоплюваний Lock "токен власника" до завдання в черзі, щоб завдання могло повторно створити блокування за допомогою даного маркера:

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

Якщо ви хочете звільнити Lock, не поважаючи його поточного власника, ви можете використовуватиforceReleaseметод:

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

Додавання власних драйверів кешу

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

Щоб створити наш власний драйвер кешу, нам спочатку потрібно реалізуватиIlluminate\Contracts\Cache\Storeконтракт. Отже, реалізація кешу 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у вихідному коді фреймворку. Після завершення нашого впровадження ми зможемо закінчити власну реєстрацію драйверів.

Cache::extend('mongo', function ($app) {
    return Cache::repository(new MongoStore);
});
Якщо вам цікаво, куди покласти власний код драйвера кеш-пам'яті, ви можете створити файлExtensionsпростір імен у вашомуappкаталог. Однак майте на увазі, що Laravel не має жорсткої структури додатків, і ви можете організувати свою заявку відповідно до своїх уподобань.

Реєстрація драйвера

Щоб зареєструвати власний драйвер кешу в Laravel, ми використаємоextendметод наCacheфасад. Заклик доCache::extendможе бути зроблено вbootметод за замовчуваннямApp\Providers\AppServiceProviderщо постачається зі свіжими програмами Laravel, або ви можете створити власного постачальника послуг для розміщення розширення - просто не забудьте зареєструвати постачальника вconfig/app.phpмасив постачальника:

<?php

namespace App\Providers;

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

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @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варіант уconfig/cache.phpфайл конфігурації. Другий аргумент - це Закриття, яке повинно повернути файлIlluminate\Cache\Repositoryінстанції. Закриття буде прийнято$appекземпляр, який є екземпляромслужбовий контейнер.

Після реєстрації вашого розширення оновітьconfig/cache.phpфайли конфігураціїdriverпараметр до імені вашого розширення.

Події

Щоб виконати код на кожній операції кешування, ви можете прослухатиподіїспрацьовує кеш. Як правило, ви повинні розміщувати ці Listeners подій у вашому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',
    ],
];