ممکن است قبلا برخی از دادههای مدل خود را در کنترلر کش کرده باشید، اما در این مقاله از لیداوب، تکنیک کش کردن دادهها در مدلها را به شما نشان میدهیم که بتوانید به دادهه
ممکن است قبلا برخی از دادههای مدل خود را در کنترلر کش کرده باشید، اما در این مقاله از لیداوب، تکنیک کش کردن دادهها در مدلها را به شما نشان میدهیم که بتوانید به دادههای خود سریعتر دسترسی داشته باشید.
با استفاده از یک کلید کش منحصر به فرد در مدل، شما میتوانید خصوصیات و ویژگیهای مدلهای لاراول خود را که به صورت خودکار در زمان بروز رسانی مدل (یا مدلهای مرتبط) آپدیت میشوند، کش کنید. مزیت اصلی این روش در این است که دسترسی به دادههای کش شده در مدل، سریعتر از دسترسی به دادههای کش شده در کنترلر است.
تکنیک کش کردن مدلها در لاراول
فرض کنید، شما یک مدل Article
دارید که دارای چند مدل Comment
مرتبط است. با توجه به قالب blade لاراول زیر، میتوانید تعداد نظرات را مانند مثال زیر در مسیر /article/:id
بازیابی کنید:
$article->comments->count() {{ str_plural('Comment', $article->comments->count())
شما میتوانید تعداد نظرات را در کنترلر خود کش کنید، ولی زمانی که کنترلر شما دارای چندین پرس و جو و اطلاعات زیادی باشد که نیاز به کش شدن دارند، این کار زیاد جالب نخواهد بود. همچنین، در کنترلر، دسترسی به دادههای کش شده سریع نخواهد بود.
میتوانیم قالبی بسازیم که وقتی مقاله آپدیت میشود، با دیتابیس ارتباط برقرار کند. در این صورت، هر کدی که به مدل دسترسی داشته باشد، میتواند مقدار کش شده را به دست آورد:
$article->cached_comments_count {{ str_plural('Comment', $article->cached_comments_count)
توسط model accessor، میتوان تعداد نظرات را براساس آخرین باری که مقاله آپدیت میشود، کش کرد.
اما زمانی که یک نظر جدید اضافه یا حذف میشود، چگونه میتوان ستون update_at
مقاله را آپدیت کرد؟ با استفاده از متد touch()
میتوان این کار را انجام داد.
مدلهای Touching
توسط متد touch()
مدل، میتوانیم ستون update_at
مقاله را آپدیت کنیم:
$ php artisan tinker
>>> $article = \App\Article::first();
=> App\Article {#746
id: 1,
title: "Hello World",
body: "The Body",
created_at: "2018-01-11 05:16:51",
updated_at: "2018-01-11 05:51:07",
}
>>> $article->updated_at->timestamp
=> 1515649867
>>> $article->touch();
=> true
>>> $article->updated_at->timestamp
=> 1515650910
میتوانیم از زمان بندی آپدیت برای باطل کردن حافظه کش استفاده کنیم، ولی زمانی که بخواهیم نظری را اضافه یا حذف کنیم، چگونه میتوانیم فیلد updated_at
مقاله را آپدیت کنیم؟
اگر مدلهای Eloquent دارای ویژگی $touches
باشند، میتوان این کار را انجام داد. در اینجا، مدل comment
را مشاهده میکنید:
<?php
namespace App;
use App\Article;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $guarded = [];
protected $touches = ['article'];
public function article()
{
return $this->belongsTo(Article::class);
}
}
ویژگی $touches
یک آرایه است که وقتی یک نظر ایجاد، ذخیره یا حذف میشود، مورد استفاده قرار میگیرد.
صفات کش شده
حالا اکسسور $ article-> cached_comments_count
را در نظر میگیریم. پیاده سازی آن در مدل App \ Article
میتواند به صورت زیر باشد:
public function getCachedCommentsCountAttribute()
{
return Cache::remember($this->cacheKey() . ':comments_count', 15, function () {
return $this->comments->count();
});
}
ما مدل را برای مدت پانزده دقیقه و با استفاده از متد cacheKey()
منحصر به فرد کش میکنیم و میتوانیم به راحتی تعداد نظرات را از تابع closure برگردانیم. توجه کنید که ما همچنین میتوانیم از متد Cache :: rememberForever()
نیز جهت حذف کلیدهای غیر مجاز استفاده کنیم.
متدcacheKey()
باید مدل را منحصر به فرد کند، یعنی هنگامی که مدل آپدیت میشود، حافظه پنهان نامعتبر میشود. در اینجا، پیاده سازی cacheKey
را مشاهده میکنید:
public function cacheKey()
{
return sprintf(
"%s/%s-%s",
$this->getTable(),
$this->getKey(),
$this->updated_at->timestamp
);
}
خروجی این مثال برای متد cacheKey()
مدل میتواند نمایش رشتهای زیر را برگرداند:
articles/1-1515650910
این کلید شامل نام جدول، شناسه مدل و زمان بندی فعلی update_at
است. زمانی که ما مدل را touch میکنیم، نشانگر زمان آپدیت میشود و کش مدل ما نامعتبر خواهد شد.
در اینجا، مدل Article
را مشاهده میکنید:
<?php
namespace App;
use App\Comment;
use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
public function cacheKey()
{
return sprintf(
"%s/%s-%s",
$this->getTable(),
$this->getKey(),
$this->updated_at->timestamp
);
}
public function comments()
{
return $this->hasMany(Comment::class);
}
public function getCachedCommentsCountAttribute()
{
return Cache::remember($this->cacheKey() . ':comments_count', 15, function () {
return $this->comments->count();
});
}
}
و مدل Comment
مرتبط:
<?php
namespace App;
use App\Article;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
protected $guarded = [];
protected $touches = ['article'];
public function article()
{
return $this->belongsTo(Article::class);
}
}
تا اینجا، مشاهده کردید که چگونه میتوان یک نظر ساده را کش کرد، اما اگر بخواهیم تمام نظرات را کش کنیم، چطور؟
public function getCachedCommentsAttribute()
{
return Cache::remember($this->cacheKey() . ':comments', 15, function () {
return $this->comments;
});
}
شما همچنین میتوانید به جای سریال سازی مدلها، نظرات را به آرایه تبدیل کنید که امکان دسترسی ساده آرایه به دادهها را در بخش فرانت اند میدهد:
public function getCachedCommentsAttribute()
{
return Cache::remember($this->cacheKey() . ':comments', 15, function () {
return $this->comments->toArray();
});
}
ما متد cacheKey()
را در مدل Article
تعریف کردیم، اما در صورت تمایل میتوانید این متد را از طریق صفتی به نام ProvidesModelCacheKey
تعریف کنید که میتوانید از آن در چند مدل استفاده کنید یا متد را در مدل پایهای که مدلهای دیگر را گسترش میدهد، تعریف کنید. شما حتی میتوانید از یک کنتراکت یا رابط برای مدلهایی که متد cacheKey()
را پیاده سازی میکنند، استفاده کنید.
برای مطالعه جدیدترین مقالات کاربردی لاراول، میتوانید کتابخانه آنلاین لیداوب را دنبال کنید.
دیدگاه ها
متاسفانه فقط اعضای سایت قادر به ثبت دیدگاه هستند
ورود به سایت