با متد QUERY یه اندپوینت جستوجوی لاراول بساز
خلاصهٔ کاملتر
پل ردموند تو لاراولنیوز سراغ متد QUERY رفته؛ یه اضافهٔ تازه به استاندارد HTTP (RFC 10008) که دقیقاً برای یه کار طراحی شده: کوئری زدن. این متد امن و کششدنیه و پارامترهاش رو تو بدنهٔ درخواست حمل میکنه — یعنی رسایی یه payload شبیه POST رو داری بدون اینکه معنای فقط-خواندنی GET رو از دست بدی و بدون اینکه مجبور باشی فیلترهای پیچیده رو تو URL بچپونی و به سقف طول آدرس بخوری.
لاراول ۱۳.۱۹ متد Http::query() رو به کلاینت HTTP اضافه کرده بههمراه هلپرهای تست query() و queryJson(). یه هلپر درستوحسابی Route::query() هم برای لاراول ۱۴ مرج شده، ولی به گفتهٔ نویسنده لازم نیست منتظر بمونی: روتر لاراول همین الان هر فعل سفارشی رو از طریق Route::match() قبول میکنه.
نویسنده صادقانه میگه یه رشتهٔ جستوجوی ساده اصلاً به QUERY نیاز نداره؛ این متد وقتی ارزشش رو نشون میده که درخواست بزرگتر از چیزی بشه که GET راحت حملش کنه: فیلترهای ساختاریافته با بازه و آرایه و گروههای and/or، کوئریهای مکانی که مختصات یه چندضلعی رو میفرستن، واکشی دستهای صدها رکورد با ID، جستوجو روی مقادیر حساس مثل ایمیل و شماره تلفن که جاشون تو URL و لاگ دسترسی و تاریخچهٔ مرورگر نیست، و اندپوینتهای گزارشگیری که در عمل خواندنیان ولی امروز بهشکل POST /reports/run مدل میشن.
نمونهٔ عملی مقاله با درایور دیتابیس Laravel Scout ساخته شده — درایوری که به سرویس جستوجوی خارجی نیاز نداره و با کوئریهای WHERE LIKE روی دیتابیس موجود کار میکنه، مناسب دیتاستهای کوچیک تا متوسط. خود روت اینشکلیه:
Route::match(['QUERY'], '/articles/search', function (Request $request) {
$validated = $request->validate([
'search' => ['required', 'string'],
'per_page' => ['sometimes', 'integer', 'between:1,50'],
]);
return Article::search($validated['search'])
->paginate($validated['per_page'] ?? 15);
});نکتهٔ خوب اینه که ولیدیشن و $request->input() دقیقاً مثل یه درخواست POST از بدنهٔ JSON میخونن و کار اضافهای لازم نیست. سمت مصرفکننده هم کلاینت HTTP لاراول میتونه اندپوینتهای QUERY رو صدا بزنه:
$response = Http::acceptJson()->query('https://example.com/api/articles/search', [
'search' => 'scout',
]);
$articles = $response->json('data');دوتا تلهٔ مهم هم هست. اول اینکه اگه با php artisan serve توسعه میدی، درخواستهای QUERY قبل از رسیدن به لاراول جواب 501 Not Implemented میگیرن، چون سرور داخلی PHP فهرست متدهای قابل قبولش رو hard-code کرده؛ محیطهای مبتنی بر Nginx مثل Herd و Valet متد رو رد میکنن به اپلیکیشن. دوم اینکه روی روتهای web.php به خطای 419 میخوری، چون میدلور PreventRequestForgery تو لاراول ۱۳ فقط GET و HEAD و OPTIONS رو خواندنی میدونه.
برای دور زدن مشکل CSRF نویسنده دو راه میذاره و صریحاً اولی رو ترجیح میده: یا میدلور رو extend کنی و متد isReading رو طوری بازنویسی کنی که QUERY هم جزو افعال خواندنی حساب بشه و بعد تو bootstrap/app.php با replace جاش بذاری، یا یه روت خاص رو با withoutMiddleware() از میدلور معاف کنی. راه دوم برای یه اندپوینت تکی جواب میده ولی باید هر بار یادت باشه و کلاً میدلور رو حذف میکنه بهجای اینکه فعل رو خواندنی طبقهبندی کنه. یه نکتهٔ تستی هم هست: میدلور CSRF تو محیط testing اصلاً بررسی نمیکنه، پس تست فیچر خطای ۴۱۹ رو نمیبینه مگه محیط رو دستی عوض کنی.
قبل از رفتن به production نویسنده چند هشدار میده: هر واسطهٔ مسیر — CDN، WAF، لود بالانسر — باید متد رو رد کنه و باید کل مسیر کلاینت تا اپ تست بشه، نه فقط خود اپ. fetch() بدون مشکل QUERY میفرسته ولی فرمهای HTML فقط GET و POST بلدن و QUERY جزو متدهای safelistشدهٔ CORS نیست، پس هر درخواست cross-origin یه preflight میخوره. مزیت کش هم فعلاً روی کاغذه: RFC این متد رو کششدنی تعریف کرده ولی مرورگرها و CDNها هنوز کش QUERY رو پیاده نکردن.
نکات کلیدی:
- QUERY (RFC 10008) پارامترها رو تو بدنه میبره ولی امن و فقط-خواندنی مثل GET میمونه
- لاراول ۱۳.۱۹: Http::query() و هلپرهای تست query()/queryJson()؛ Route::query() برای لاراول ۱۴
- تا اون موقع Route::match(['QUERY'], ...) کار میکنه و ولیدیشن از بدنهٔ JSON میخونه
- php artisan serve جواب ۵۰۱ میده؛ Herd و Valet مشکلی ندارن
- روی روتهای وب خطای ۴۱۹ میگیری؛ بهترین راه، افزودن QUERY به افعال خواندنی در isReading
- ارزش واقعیش تو فیلترهای پیچیده، کوئری مکانی، و مقادیر حساسیه که نباید تو URL باشن




