
دسترسی سریع به عناوین این مقاله
تصور کنید که یک پروژه لاراولی دارید که لیست درخواست های یک سیستم تیکت را به همراه وضعیت هر درخواست نمایش میدهد.
کارفرما از شما درخواست میکند که در بالای صفحه 3 کادر طراحی کنید که داخل هر کادر تعداد کل درخواست ها، انجام شده، در حال پیگیری را نشان دهد.

خب!
حالا چطور به بهترین روش ممکن این تعداد ها را دریافت کنیم؟
یک راهکار این است که چند کوئری جداگانه به دیتابیس بزنیم که تعداد درخواست های هر وضعیت را حساب کند. این راه را امتحان می کنیم.
public function index()
{
$statuses = (object)[];
$statuses->requested = Feature::where('status','requested')->count();
$statuses->planned = Feature::where('status','planned')->count();
$statuses->completed = Feature::where('status','completed')->count();
$features = Feature::query()
->withCount('comments')
->paginate();
return view('features', [
'statuses' => $statuses,
'features' => $features,
]);
}
اگر به کدهای بالا نگاه کنیم، سه کوئری ای که برای به دست آوردن تعداد ها زده ایم را می بینیم که در این شرایط مشکل خاصی نیست چون تنها سه وضعیت داریم.
اما اگر 5 وضعیت داشتیم چه؟ یا 10 یا حتی بیشتر از آن. این همان وقتی است که کوئری های جدا مشکل ایجاد می کنند.
می خواهم به شما تکنیکی که در توابع aggregation در لاراول است و در این شرایط استفاده می کنم را نشان دهم.
توابع aggregation در لاراول
به سراغ یک ابزار مدیریت دیتابیس مانند table plus یا PhpMyadmin یا Navicat بروید تا کوئری را آن جا به دست آوریم. (خودم از navicate استفاده میکنم)
در اصل راهی وجود دارد که بتوانیم این تعداد ها را با یک کوئری به دست آوریم. احتمالا با نوشتن کوئری ای مانند زیر آشنایی دارید.
SELECT COUNT(*) from features
اگر این کوئری را اجرا کنید نتیجه آن 60 خواهد بود.
چیزی که احتمالا نمی دانید این است که می توان دستورهای شرطی را داخل توابعی مانند COUNT و SUM و… نوشت. به کوئری بالا شرط اضافه می کنیم.
SELECT COUNT(CASE WHEN status = 'Requested' THEN 1 END) from features
اگر کوئری بالا را اجرا کنیم نتیجه آن 47 خواهد بود. اگر به صفحه اصلی برنامه نگاه کنیم می بینیم که این مقدار درست است. حال یک شرط دیگر اضافه می کنیم.
SELECT
COUNT(CASE WHEN status = 'Requested' THEN 1 END),
COUNT(CASE WHEN status = 'Planned' THEN 1 END)
from features
اگر این کوئری را اجرا کنیم دو تعداد در نتیجه می گیریم 47 و 3 که هر دو درست اند. این کار را برای وضعیت سوم هم انجام می دهیم.
SELECT
COUNT(CASE WHEN status = 'Requested' THEN 1 END),
COUNT(CASE WHEN status = 'Planned' THEN 1 END),
COUNT(CASE WHEN status = 'Completed' THEN 1 END)
from features
با اجرای کوئری بالا این نتیجه را دریافت می کنیم.

جمع این سه عدد 60 می شود که تعداد کل درخواست ها بود. البته در حال حاضر اسم ستون هایی که در نتیجه آمده اند خوب نیست. به همین خاطر به هر کدام از آن ها یک نام مستعار می دهیم.
SELECT
COUNT(CASE WHEN status = 'Requested' THEN 1 END) as requested,
COUNT(CASE WHEN status = 'Planned' THEN 1 END) as planned,
COUNT(CASE WHEN status = 'Completed' THEN 1 END) as completed
from features
اکنون نتیجه ای مانند زیر دریافت می شود.

حال به کنترلر FeatureController
می رویم تا کوئری را در آنجا بنویسیم.
public function index()
{
$statuses = Feature::toBase()
->selectRaw("count(case when status = 'Requested' then 1 end) as requested")
->selectRaw("count(case when status = 'Planned' then 1 end) as planned")
->selectRaw("count(case when status = 'Completed' then 1 end) as completed")
->first();
$features = Feature::query()
->withCount('comments')
->paginate();
return view('features', [
'statuses' => $statuses,
'features' => $features,
]);
}
به این دلیل که نمی خواهیم نتیجه دریافتی یک شی از مدل Feature باشد متد toBase
را صدا زدیم (با اجرای این متد مدل به دست آمده به شی ای از query builder تبدیل می شود). سپس از متد selectRaw
برای نوشتن کوئری استفاده کردیم و در نهایت از آن جایی که می دانیم این کوئری تنها یک row بر می گرداند متد first
را به جای get
صدا زدیم.
- تغییر اندازه عکس در PHP یا لاراول
- لیست شرکت های خلاق حوزه کسب و کارهای دیجیتال و فضای مجازی
- الگوریتم اعتبارسنجی کد شبا بانکی
- آشنایی با پیام های http
- مقدمه آموزش اصول برنامه نویسی