Form Request پیشرفته در Laravel — validation، authorization و prepare
Form Request در Laravel validation و authorization را از Controller جدا میکند. بیشتر پروژهها با rules() ساده شروع میکنند؛ پروژه واقعی به قوانین شرطی، normalize ورودی و پیام فارسی نیاز دارد.
چرخه Form Request
authorize()— 403 اگر falseprepareForValidation()— normalize قبل از validaterules()+ messages/attributespassedValidation()/withValidator()— after hooks
authorize با Policy
public function authorize(): bool
{
return $this->user()->can('create', Post::class);
}
Policy — منطق مجوز یک جا.
prepareForValidation — normalize
protected function prepareForValidation(): void
{
$this->merge([
'slug' => Str::slug($this->input('title')),
'phone' => preg_replace('/\D/', '', $this->input('phone', '')),
]);
}
ورودی تمیز قبل از rule — شماره موبایل ایران یکدست.
قوانین شرطی
public function rules(): array
{
return [
'type' => ['required', Rule::in(['personal', 'company'])],
'company_name' => [
Rule::requiredIf($this->input('type') === 'company'),
'string', 'max:255',
],
'national_id' => [
Rule::requiredIf($this->input('type') === 'personal'),
'digits:10',
],
];
}
withValidator — after validation
public function withValidator(Validator $validator): void
{
$validator->after(function (Validator $validator) {
if ($this->couponInvalid()) {
$validator->errors()->add('coupon', 'کد تخفیف معتبر نیست.');
}
});
}
برای cross-field یا query DB بعد از rules پایه.
پیام و attribute فارسی
public function messages(): array
{
return [
'title.required' => 'عنوان مقاله الزامی است.',
'slug.unique' => 'این آدرس قبلاً استفاده شده.',
];
}
public function attributes(): array
{
return ['title' => 'عنوان', 'slug' => 'نامک'];
}
Custom Rule class
'slug' => ['required', new UniquePostSlugExcept($this->route('post'))],
قابل تست جدا — unit test.
تبدیل به DTO
public function toDto(): CreatePostData
{
return CreatePostData::fromArray($this->validated());
}
DTO.
API vs Web Form Request
همان کلاس — failedValidation override برای JSON 422:
protected function failedValidation(Validator $validator)
{
throw new HttpResponseException(response()->json([
'message' => 'Validation failed',
'errors' => $validator->errors(),
], 422));
}
اشتباهات
- validation در Controller تکراری
- authorize همیشه true
- query سنگین در rules بدون cache
جمعبندی
Form Request مرز ورودی HTTP است. Action فقط validated/DTO میگیرد. Clean Code.