ستونهای Generated و ویوهای SQL تو لاراول
خلاصهٔ کاملتر
نویسنده تو این مقالهٔ Tighten سراغ دو قابلیت بومی SQL رفته که خیلی وقتها میتونن جای منطق اپلیکیشن رو بگیرن: ستونهای Generated و ویوهای جدول. ستون Generated مقدارش خودکار از روی یه عبارت روی ستونهای دیگهٔ همون ردیف حساب میشه و دو نوع داره؛ VIRTUAL که موقع کوئری محاسبه میشه و STORED که روی دیسک ذخیره میشه و با تغییر ردیف بهروز میشه. اکثر موتورهای مدرن مثل MySQL، MariaDB و PostgreSQL پشتیبانیش میکنن.
شباهتش به اکسسور Eloquent زیاده، ولی به گفتهٔ نویسنده تفاوتها تعیینکنندهان. اکسسور بعد از خوندهشدن داده از دیتابیس اجرا میشه، پس نه میشه باهاش فیلتر و مرتبسازی کرد نه ایندکس ساخت، و اگه با Query Builder یا SQL خام کوئری بزنی اصلاً وجود نداره. ستون Generated چون جزو اسکیمای واقعیه، تو هر سه حالت میاد و تو WHERE و ORDER BY هم کار میکنه.
تعریفش تو مایگریشن لاراول با storedAs() و virtualAs() انجام میشه؛ مثلاً یه ستون ذخیرهشده بههمراه ایندکس:
Schema::table('products', function (Blueprint $table) {
$table->decimal('full_price', 10, 2)
->storedAs('price * tax_rate')
->index();
});بعدش full_price مثل هر ستون دیگهای قابل فیلتر و مرتبسازیه. فقط حواست باشه ستون virtual رو میشه فیلتر و مرتب کرد ولی نمیشه ایندکسش کرد.
بخش دوم مقاله دربارهٔ ویوهاست: یه کوئری SELECT ذخیرهشده که میتونه جوین بزنه، فیلد حساب کنه و شرط بذاره، و لاراول مثل یه جدول فقطخواندنی میبینتش. مثال نویسنده یه فروشگاهه که قیمت تخفیفخورده رو از جوین جدول promotions درمیاره:
CREATE VIEW price_list AS
SELECT
p.id,
p.name,
p.price * (1 - pr.discount) AS discounted_price
FROM products p
LEFT JOIN promotions pr ON CURRENT_DATE BETWEEN pr.start_date AND pr.end_dateنویسنده پیشنهاد میکنه ویو رو با DB::statement داخل مایگریشن بسازی تا بقیهٔ تیم هم ازش خبر داشته باشن، و در صورت نیاز یه مدل Eloquent با $table = 'price_list' براش تعریف کنی — فقط یادت باشه اون مدل فقطخواندنیه و رکورد جدید باید از جدول اصلی ساخته بشه.
برای اینکه فرقش معلوم بشه، نویسنده یه سناریوی واقعی میسازه: صفحهٔ حاشیهٔ سود که با اکسسور و sortByDesc روی کالکشن کار میکرد و مجبور بود همهٔ رکوردها رو تو حافظه بیاره. بعد از تبدیلش به ستون stored ایندکسدار، زمان از حدود ۳۵۰ به ۷۰ میلیثانیه رسید و صفحهبندی هم ممکن شد. تو گزارش فروش روزانه هم جایگزینی گروهبندی در PHP با GROUP BY و جوین، زمان رو از حدود ۱۶۶۵ به ۱۵۷ میلیثانیه آورد.
با این حال نویسنده میگه همیشه نباید سراغ ستون Generated رفت: اگه منطقت پیچیدهست، به دادهٔ بیرونی مثل متغیر محیطی یا کاربر لاگینکرده نیاز داری، یا دیتاست کوچیکه و قرار نیست فیلتر و ایندکس بشه، همون اکسسور انتخاب بهتریه. حرف آخرش هم اینه که ستونهای Generated و ویوها رو حتماً با مایگریشن بساز تا سورس حقیقت همون کدبیس بمونه.
نکات کلیدی:
- ستون Generated مقدارش رو از روی ستونهای همون ردیف حساب میکنه؛ virtual موقع کوئری، stored روی دیسک
- برخلاف اکسسور، تو Eloquent و Query Builder و SQL خام هر سه در دسترسه و تو WHERE و ORDER BY کار میکنه
- ستون virtual قابل فیلتر و مرتبسازیه ولی ایندکس نمیگیره؛ برای ایندکس باید stored باشه
- ویو یه کوئری SELECT ذخیرهشدهست که لاراول مثل جدول فقطخواندنی میبینتش و میشه براش مدل ساخت
- تو بنچمارکهای مقاله، انتقال محاسبه و مرتبسازی به دیتابیس حدود ۸۰٪ و تو مورد دوم بیش از ۱۰ برابر سرعت آورد
- اکسسور برای منطق پیچیده یا وابسته به دادهٔ بیرونی هنوز انتخاب بهتریه




