نسخه:

حافظه پنهان

معرفی

برخی از وظایف بازیابی یا پردازش داده‌ها که توسط برنامه شما انجام می‌شود ممکن است به CPU فشرده یا چند ثانیه طول بکشد. در این مورد، معمول است که داده‌های بازیابی شده را برای مدتی در حافظه پنهان نگه می‌دارند تا بتوان در درخواست‌های بعدی برای همان داده‌ها به سرعت بازیابی شوند. داده‌های کش معمولاً در یک انبار داده بسیار سریع مانند Memcached یا Redis ذخیره می‌شوند .

خوشبختانه، لاراول یک API گویا و یکپارچه برای پشتیبان‌های کش مختلف ارائه می‌کند که به شما امکان می‌دهد از بازیابی سریع داده‌ها و سرعت بخشیدن به برنامه وب خود استفاده کنید.

پیکربندی

فایل پیکربندی کش برنامه شما در آدرس قرار دارد config/cache.php . در این فایل، می‌توانید مشخص کنید که می‌خواهید از کدام حافظه پنهان به‌طور پیش‌فرض در سراسر برنامه‌تان استفاده شود. لاراول از پشتیبان‌های کش محبوب مانند Memcached ، Redis ، DynamoDB و پایگاه‌های داده رابطه‌ای خارج از جعبه پشتیبانی می‌کند. علاوه بر این، یک درایور کش مبتنی بر فایل در دسترس است، در حالی که array درایورهای کش "تهی" پشتیبان های کش مناسبی را برای تست های خودکار شما فراهم می کنند.

فایل پیکربندی کش همچنین شامل گزینه های مختلفی است که می توانید آنها را مرور کنید. به‌طور پیش‌فرض، لاراول به گونه‌ای پیکربندی شده است که از database درایور کش استفاده کند، که اشیاء سریال‌سازی شده و کش را در پایگاه داده برنامه شما ذخیره می‌کند.

پیش نیاز راننده

پایگاه داده

هنگام استفاده از database درایور کش، به یک جدول پایگاه داده نیاز دارید که حاوی داده های کش باشد. به طور معمول، این در 0001_01_01_000001_create_cache_table.php انتقال پایگاه داده پیش فرض لاراول گنجانده شده است . با این حال، اگر برنامه شما حاوی این مهاجرت نیست، می توانید از make:cache-table دستور Artisan برای ایجاد آن استفاده کنید:

php artisan make:cache-table
 
php artisan migrate

Memcached

استفاده از درایور Memcached مستلزم نصب بسته Memcached PECL است. می توانید تمام سرورهای Memcached خود را در config/cache.php فایل پیکربندی فهرست کنید. این فایل از قبل حاوی یک memcached.servers ورودی برای شروع است:

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

در صورت نیاز، می توانید این host گزینه را روی یک مسیر سوکت یونیکس تنظیم کنید. اگر این کار را انجام دهید، port گزینه باید روی 0 :

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

ردیس

قبل از استفاده از کش Redis با لاراول، باید افزونه PhpRedis PHP را از طریق PECL نصب کنید یا predis/predis بسته (~2.0) را از طریق Composer نصب کنید. Laravel Sail در حال حاضر شامل این افزونه است. علاوه بر این، پلتفرم های رسمی استقرار لاراول مانند Laravel Forge و Laravel Vapor دارای پسوند PhpRedis هستند که به طور پیش فرض نصب شده اند.

برای اطلاعات بیشتر در مورد پیکربندی Redis، به صفحه اسناد لاراول آن مراجعه کنید .

DynamoDB

قبل از استفاده از درایور کش DynamoDB ، باید یک جدول DynamoDB برای ذخیره تمام داده های کش شده ایجاد کنید. به طور معمول، این جدول باید نامگذاری شود cache . با این حال، شما باید جدول را بر اساس مقدار مقدار stores.dynamodb.table پیکربندی در cache فایل پیکربندی نامگذاری کنید. نام جدول ممکن است از طریق DYNAMODB_CACHE_TABLE متغیر محیطی نیز تنظیم شود.

این جدول همچنین باید دارای یک کلید پارتیشن رشته ای با نامی باشد که با مقدار stores.dynamodb.attributes.key آیتم پیکربندی در فایل پیکربندی برنامه شما مطابقت دارد cache . به طور پیش فرض، کلید پارتیشن باید نامگذاری شود key .

استفاده از کش

به دست آوردن یک نمونه کش

برای به دست آوردن نمونه فروشگاه کش، می توانید از Cache نما استفاده کنید، که ما در سراسر این مستندات از آن استفاده خواهیم کرد. نما Cache دسترسی راحت و مختصری به پیاده سازی های اساسی قراردادهای کش لاراول فراهم می کند:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Support\Facades\Cache;
 
class UserController extends Controller
{
/**
* Show a list of all users of the application.
*/
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 Minutes

بازیابی موارد از حافظه پنهان

روش Cache نما get برای بازیابی آیتم ها از حافظه پنهان استفاده می شود. اگر مورد در کش وجود نداشته باشد، 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 ممکن است برای تنظیم مقدار موارد اعداد صحیح در حافظه پنهان استفاده شوند. هر دوی این روش‌ها یک آرگومان دوم اختیاری را می‌پذیرند که میزان افزایش یا کاهش ارزش آیتم را نشان می‌دهد:

// Initialize the value if it does not exist...
Cache::add('key', 0, now()->addHours(4));
 
// Increment or decrement the 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();
});

اگر آیتم در کش وجود نداشته باشد، بسته شدن به 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();

شستشوی کش به «پیشوند» کش پیکربندی شده شما احترام نمی گذارد و همه ورودی ها را از کش حذف می کند. هنگام پاک کردن حافظه پنهانی که توسط سایر برنامه ها به اشتراک گذاشته شده است، به دقت در نظر بگیرید.

کمک کننده حافظه پنهان

علاوه بر استفاده از 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 کش به عنوان درایور کش پیش فرض برنامه شما استفاده کند. علاوه بر این، همه سرورها باید با یک سرور حافظه مرکزی یکسان در ارتباط باشند.

مدیریت قفل ها

قفل های اتمی امکان دستکاری قفل های توزیع شده را بدون نگرانی در مورد شرایط مسابقه فراهم می کنند. به عنوان مثال، لاراول فورج از قفل های اتمی استفاده می کند تا اطمینان حاصل کند که تنها یک وظیفه از راه دور در یک سرور در یک زمان اجرا می شود. شما می توانید قفل ها را با استفاده از روش زیر ایجاد و مدیریت کنید Cache::lock :

use Illuminate\Support\Facades\Cache;
 
$lock = Cache::lock('foo', 10);
 
if ($lock->get()) {
// Lock acquired for 10 seconds...
 
$lock->release();
}

روش get بسته شدن را نیز می پذیرد. پس از اجرای بسته شدن، لاراول به طور خودکار قفل را آزاد می کند:

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

اگر قفل در لحظه ای که شما آن را درخواست می کنید در دسترس نیست، می توانید به لاراول دستور دهید که برای تعداد مشخصی از ثانیه صبر کند. اگر نتوان قفل را در مدت زمان مشخص شده بدست آورد، یک عدد Illuminate\Contracts\Cache\LockTimeoutException پرتاب می شود:

use Illuminate\Contracts\Cache\LockTimeoutException;
 
$lock = Cache::lock('foo', 10);
 
try {
$lock->block(5);
 
// Lock acquired after waiting a maximum of 5 seconds...
} catch (LockTimeoutException $e) {
// Unable to acquire lock...
} finally {
$lock?->release();
}

مثال بالا ممکن است با عبور دادن یک بسته به block روش ساده شود. هنگامی که یک بسته به این روش منتقل می شود، لاراول تلاش می کند تا قفل را برای تعداد ثانیه مشخص شده بدست آورد و پس از اجرای بسته شدن به طور خودکار قفل را آزاد می کند:

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

مدیریت قفل ها در سراسر فرآیندها

گاهی اوقات، ممکن است بخواهید در یک فرآیند یک قفل را بدست آورید و در فرآیندی دیگر آن را آزاد کنید. به عنوان مثال، ممکن است در طول یک درخواست وب، قفلی را به دست آورید و بخواهید در پایان یک کار در صف که توسط آن درخواست ایجاد می شود، قفل را آزاد کنید. در این سناریو، شما باید "Token مالک" قفل را به کار در صف ارسال کنید تا کار بتواند با استفاده از نشانه داده شده، قفل را مجدداً نمونه برداری کند.

در مثال زیر، اگر یک قفل با موفقیت به دست آمد، یک کار در صف ارسال می کنیم. علاوه بر این، توکن مالک قفل را از طریق روش قفل به کار در صف ارسال می کنیم 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 قرارداد را پیاده سازی کنیم . بنابراین، یک پیاده سازی کش 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 :

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

اگر نمی‌خواهید کد درایور کش سفارشی خود را کجا قرار دهید، می‌توانید یک Extensions فضای نام در app فهرست خود ایجاد کنید. با این حال، به خاطر داشته باشید که لاراول ساختار نرم افزاری سفت و سختی ندارد و شما آزاد هستید که برنامه خود را بر اساس ترجیحات خود سازماندهی کنید.

ثبت درایور

برای ثبت درایور کش سفارشی با لاراول extend از روش Cache نما استفاده می کنیم. از آنجایی که سایر ارائه دهندگان خدمات ممکن است سعی کنند مقادیر ذخیره شده را در روش خود بخوانند boot ، ما درایور سفارشی خود را در یک booting تماس برگشتی ثبت می کنیم. با استفاده از booting callback، می‌توانیم اطمینان حاصل کنیم که درایور سفارشی درست قبل از boot فراخوانی متد در ارائه‌دهندگان خدمات برنامه ما ثبت شده است، اما پس از register فراخوانی متد در همه ارائه‌دهندگان خدمات. ما booting callback خود را در 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
{
/**
* Register any application services.
*/
public function register(): void
{
$this->app->booting(function () {
Cache::extend('mongo', function (Application $app) {
return Cache::repository(new MongoStore);
});
});
}
 
/**
* Bootstrap any application services.
*/
public function boot(): void
{
// ...
}
}

اولین آرگومان ارسال شده به extend متد، نام درایور است. این با driver گزینه شما در فایل پیکربندی مطابقت دارد config/cache.php . آرگومان دوم بسته شدن است که باید یک Illuminate\Cache\Repository نمونه را برگرداند. بسته شدن یک نمونه ارسال می‌شود $app ، که نمونه‌ای از کانتینر سرویس است .

پس از ثبت برنامه افزودنی، CACHE_STORE متغیر محیطی یا default گزینه موجود در فایل پیکربندی برنامه خود config/cache.php را به نام برنامه افزودنی خود به روز کنید.

مناسبت ها

برای اجرای کد در هر عملیات کش، می توانید به رویدادهای مختلفی که توسط کش ارسال می شود گوش دهید:

نام رخداد
Illuminate\Cache\Events\CacheHit
Illuminate\Cache\Events\CacheMissed
Illuminate\Cache\Events\KeyForgotten
Illuminate\Cache\Events\KeyWritten