تقریبا در هر برنامه تحت وب که تعداد قابل توجهی کاربر دارد به کش (cache) نیاز داریم. چه به خاطر تجربه کاربری بهتر و کمک به سئو و چه به خاطر کاهش هزینهها یا استفاده بهینه از منابع سرور.
در این مطلب یاد میگیریم که در لاراول چطور از cache استفاده کنیم.
چرا به کش کردن اطلاعات در نرم افزار نیاز داریم؟
وقتی با مرورگر یک صفحه وب را باز میکنیم به آن آدرس یک درخواست(request) ارسال میشود. سرور این درخواست را پردازش می کند و به ما پاسخ میدهد.
گاهی زمان پردازش اطلاعات بالاست و سرور مدت زمان بیشتری درگیر است و منابع بیشتری مصرف میکند. در نتیجه ما به عنوان کاربر زمان بیشتری منتظر میمانیم و شاهد چرخیدن دایره لودینگ مرورگر هستیم.
یکی از راه حل های این مسئله استفاده از cache است. یعنی اینکه این پاسخی که قرار است از سرور دریافت کنیم یکبار پردازش شود و در مراجعه بعدی کاربران به آن آدرس دیگر مرحله پردازش اطلاعات وجود نداشته باشد.
حالا سرور تنها کاری که میکند نمایش اطلاعات از قبل ذخیره شده است. به همین خاطر سرعت نرم افزار بالاتر میرود.
چه چیزهایی را باید در یک نرم افزار تحت وب کش کنیم؟
- کوئریهایی که به دیتابیس میزنیم و نتیجه آن ها دیر به دیر تغییر می کند(مثلا دریافت یک دسته بندی خاص از محصولات).
- تنظیمات نرم افزار.
- اطلاعات صفحاتی که معمولا ثابت هستند مثل صفحه اصلی سایت یا صفحات وبلاگ که مقالات در آن قرار دارند.
نحوه کار باcache در لاراول
قبل از استفاده از کش باید یک درایور برای آن تعریف کنیم. یعنی مشخص کنیم این کش توسط چه ابزاری انجام میشود.
لاراول به صورت پیشفرض از فایل برای کش کردن اطلاعات استفاده میکند. این را میتوانیم در فایل تنظیمات کش در مسیرconfig/cache.php
تغییر بدهیم.
اگر نگاهی به فایل cache.php
بندازید یک ثابت به شکل زیر تعریف شده است.
'default' => env('CACHE_DRIVER', 'file'),
شما می توانید در فایل .env
با تغییر مقدار CACHE_DRIVER
از redis یا database هم استفاده کنید. dynamodb هم که برای آمازون است و استفاده از آن در ایران رایج نیست.
برای کار با redis باید یک مطلب جداگانه نوشت. اما اینجا به file و database اشاره خواهیم کرد.
برای استفاده از file برای cache تنها کافی است که مقدار default CACHE_DRIVER
را به file
تغییر بدهیم.
اما برای استفاده از database به cache، باید یک جدول بسازیم.
ایجاد جدول برای کش در دیتابیس
با استفاه از دستور php artisan cache:table
یک migration جدید برای کش درست می شود.
Schema::create('cache', function ($table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
اطلاعاتی که در دیتابیس کش میشوند در این جدول قرار میگیرند.
بعد از این کهمشخص کردیم اطلاعات موجد در کش کجا قرار بگیرند حالا می رویم سراغ نحوه کار با cache.
برای کار با کش در لاراول از یک Facade به نام Cache
استفاده میکنیم.
ذخیره یک مقدار در کش
با متد put
یک آیتم را در کش ذخیره میکنیم.
use Illuminate\Support\Facades\Cache;
public function index(){
$products = Product::all();
Cache::put('products',$products,3600);
}
اینجا محصولات را با کلید products
به مدت 3600 ثانیه کش کردیم.
اگر پارامتر سوم یعنی زمان را ذکر نکنیم. بدون محدودیت زمانی در کش خواهد ماند.
دریافت یک مقدار از کش
فرض میکنیم یک مقدار در کش ذخیره شده. با متد get آن را دریافت میکنیم.
use Illuminate\Support\Facades\Cache;
class ProductController extends controller
{
public function index(){
$products = Cache::get('products');
}
}
کلاس Cache
یک متد get
دارد که یک پارامتر میپذیرد. هر مقداری که در کش ذخیره می شود یک key دارد که با استفاده از آن مقدار کش را دریافت میکنیم. اگر مقداری که دنبال آن میگردید وجود نداشته باشد null برگشت داده میشود. در چنین شرایطی میتوانید یک مقدار پیشفرض بگذارید تا جای null قرار بگیرد.
Cache::get('key','default');
یک closure هم به عنوان مقدار پیشفرض میتوانیم قرار بدهیم.
مثال:
use Illuminate\Support\Facades\Cache;
class ProductContoller extends Controller
{
public function index(){
$result = Cache::get('products',function(){
return App\Models\Product::all();
});
}
در این مثال اگر در کلید products اطلاعاتی ذخیره نشده بود مقدار خروجی داخل closure برگشت داده میشود
دریافت و ذخیره همزمان از کش
با متد Remember
می توانیم دو کار را همزمان انجام دهیم. یک مقدار را از کش دریافت کنیم و اگر وجود نداشت آن را بگیریم و در کش ذخیره کنیم.
Cache::remember('products',$seconds,function(){
return App\Models\Product::all();
});
پارامتر دوم زمان ماندن در کش بر حسب ثانیه است. اگر به جای remember
از rememberForever
استفاده کنیم. مقدار برای همیشه ذخیره خواهد شد.
مثال:
use Illuminate\Support\Facades\Cache;
class ProductContoller extends Controller
{
public function index(){
Cache::remember('products',60,function(){
return Product::all();
});
$products = Cache::get('products');
dd($products);
}
}
چک کنیم که آیا چنین مقداری در کش هست یا خیر
برای چک کردن موجودی در کش از متد has
استفاده میکنیم. مقدار بازگشتی true
یا false
خواهد بود.
if(Cache::has('key')){
//do something
}
دریافت از کش و حذف مقدار
متد pull
یک مقدار را از کش میگیرد و بعد آن را حذف می کند.
Cache::pull(products);
مثال:
//controller
public function index(){
Cache::remember('products',60,function(){
return Product::all();
});
$products = Cache::pull('products');
$has_cache = Cache::has('products');
dd($products,$has_cache);
}
در مثال بالا اول مقدار products
را در کش قرار دادیم بعد با متد pull
آن را در متغیر $products
گذاشتیم و همزمان از cache حذف کردیم.
الان باید cache از این مقدار خالی شده باشد ولی در متغیر $products
وجود داشته باشد. با تابع dd
هر دو مورد را تست کردیم و نتیجه درست بود.
ذخیره در کش اگر مقدار مورد نظرمان وجود ندارد
با متد add
اگر مقداری که میخواهیم در کش نبود آن را ذخیره میکنیم.
Cache::add('key','value',$seconds);
حذف مقدار از کش
متد forever
یک مقدار را از برای همیشه در cache ذخیره میکند. اگر دیگر به آن مقدار نیاز نداشتید باید به صورت دستی حذفش کنید.
Cache::forever('products',$products);
پاک کردن همه مقادیر استفاده شده در cache
متد flush
همه مقادیری که در cache ذخیره کردهایم را پاک خواهد کرد.
Cache::flush();
تگ گذاری کشها
میتوانیم برای مقادیری که در کش ذخیره میکنیم تگ یا برچسب بگذاریم. با این کار آنها را دسته بندی میکنیم.
Cache::tags(['product'])->put('books',$books,3600);
Cache::tags(['product'])->put('notebooks',$notebooks,3600);
در کد بالا هم مقدار books و هم مقدار notebooks در تگ product قرار گرفتند.
چه مواقعی به تگ گذاری کش ها نیاز داریم؟
کاربرد اصلی تگ گذاری برای وقتی است که میخواهیم مجموعهای از مقادیر مربوط به هم در cache را حذف کنیم.
به این مثال توجه کنید:
فرض کنید در چند جای مختلف از نرم افزار چند رکورد از جدول products
را در کش ذخیره کردهایم. بعد از مدتی که اطلاعات محصولات به روز شد، نیاز داریم که همه این اطلاعات کش شده را پاک کنیم. اگر کلیدهای آنها را تگ گذاری کرده باشیم با اجرای یک دستور همه پاک خواهند شد.
Cache::tags(['products'])->flush();
دریافت مقدار با تگ مشخص
برای دریافت مقدارهایی که تگ گذاری شدهاند تگ های آنها را به متد tags پاس میدهیم بعد با متد get آن مقدار را دریافت میکنیم.
Cache::tags(['products'])->get('books');
در متد tags می توایم چند برچسب را به عنوان پارامتر قرار بدهیم.
جمع بندی
دیدیم که کار با cache در لاراول خیلی ساده است اما وقتی تصمیم می گیریم از کش استفاده کنیم این نکته را یادمان باشد:
استفاده از کش به هیچ وجه یک راه حل کامل و قطعی برای بهینه سازی نرم افزار نیست و قرار نیست که همه مشکلات عملکردی وبسایت یا وب اپلیکشن را حل کند. اما در کنار مواردی مثل استفاده از سرور مناسب، نوشتن کوئری های بهینه، کاهش حجم تصاویر و کاهش تعداد requestها میتوان از آن استفاده کرد.
دمتون گرم خیلی شفاف توضیح دادید
خواهش میکنم