لاراول ۱۳.۳۳ ستونهای محاسبهشده رو خودکار میخونه
خلاصهٔ کاملتر
تو این مقاله لاراولنیوز اومده که اگه یه ستون رو خود دیتابیس حساب کنه، مدل Eloquent ازش بیخبر میمونه. مثلاً تو جدول orders ستون total با storedAs از جمع subtotal و tax ساخته میشه؛ بعد از Order::create() مقدار total روی مدل null هست و بعد از update هم همون مقدار قدیمی میمونه. راهحل قبلی این بود که دستی refresh() صدا بزنی، که کل ردیف و همه رابطههای لودشده رو از نو میخونه.
لاراول ۱۳.۳۳ برای همین، اتریبیوت #[Refreshes] رو اضافه کرده؛ کار Caleb White تو پولریکوئست ۶۱۵۲۳. کافیه اسم ستونهایی که دیتابیس پرشون میکنه رو روی کلاس مدل بنویسی:
#[Refreshes('total')]
class Order extends Model
{
protected $fillable = ['subtotal', 'tax'];
}بعد از هر insert یا update، Eloquent همون ستونها رو برای ردیف ذخیرهشده میخونه و روی مدل میذاره:
$order = Order::create(['subtotal' => 100, 'tax' => 8.25]);
$order->total; // "108.25"
$order->update(['tax' => 9.00]);
$order->total; // "109.00"رفرش بین اجرای INSERT/UPDATE و رویدادهای created و updated انجام میشه، پس یه observer میتونه total حسابشده رو بخونه و wasChanged('total') هم درست جواب میده. اگه ترجیح میدی با پروپرتی کار کنی، $refreshes رو ست کن؛ وقتی هر دو باشن، پروپرتی برندهست و اتریبیوت نادیده گرفته میشه.
کوئری رفرش یه SELECT ساده روی کلید اصلیه که روی کانکشن write اجرا میشه، پس با read replica این خطر رو نداره که ردیف تازه هنوز به رپلیکا نرسیده باشه. global scopeها رو هم رد میکنه تا اسکوپ tenant یا soft-delete ردیفی که همین الان ذخیره شده رو قایم نکنه. ولی چون با firstOrFail() اجرا میشه، اگه ردیف تا لحظه اجرای کوئری پاک شده باشه، save یه ModelNotFoundException میندازه.
نکات کلیدی:
- اتریبیوت #[Refreshes] تو لاراول ۱۳.۳۳ اضافه شده (پولریکوئست ۶۱۵۲۳ از Caleb White)
- برای چند ستون، آرایه یا چند آرگومان بده؛ #[Refreshes(['total', 'slug'])] و #[Refreshes('total', 'slug')] یکیان
- روی create/save/saveQuietly/saveOrIgnore و update/save/saveQuietly و همچنین increment و decrement اجرا میشه
- مدلی که نه اتریبیوت داره نه پروپرتی $refreshes، هیچ کوئری اضافهای نمیزنه
- برای خوندن کل ردیف یا رابطههای لودشده، همون refresh() دستی جواب میده




