پرش به مطلب اصلی

Form Validation

این صفحه نحوه استفاده از قابلیت FormValidation در Doravel را توضیح می‌دهد.
هدف این قابلیت این است که ruleهای نوشته‌شده در FormRequest علاوه بر submit نهایی، برای validation سمت فرم هم استفاده شوند.

قاعده اصلی

قاعده‌های اعتبارسنجی را در FormRequest نگه دارید.
در Doravel همان ruleها مبنای validation سمت فرم هستند و در submit نهایی هم Laravel دوباره همان‌ها را اجرا می‌کند.

class StoreUserRequest extends FormRequest
{
public function rules(): array
{
return [
'name' => ['required', 'string', 'max:128'],
'mobile' => ['required', 'mobile'],
];
}
}

force_remote

به صورت پیش‌فرض، Doravel هر ruleای را که بتواند در JavaScript بررسی کند، همان‌جا بررسی می‌کند.
اما بعضی ruleها باید از سمت سرور بررسی شوند؛ مثلا ruleهای سفارشی، exists و unique.

این ruleها خودشان remote می‌شوند و لازم نیست فقط برای remote شدن به آن‌ها force_remote اضافه کنید.

force_remote برای وقتی است که یک rule ساده، که معمولا در JavaScript هم قابل بررسی است، حتما از سمت backend بررسی شود. با این کار برای آن فیلد request remote ارسال می‌شود.

چه زمانی استفاده شود؟

  • وقتی rule ساده‌ای مثل required، date، after، min یا max باید از سمت backend بررسی شود
  • وقتی نتیجه rule به اطلاعاتی وابسته است که فقط سرور درست می‌داند
  • وقتی نتیجه یک rule ساده به مقدار فیلدهای دیگر فرم وابسته است
  • وقتی می‌خواهید Laravel معیار نهایی validation همان فیلد باشد، نه JavaScript

مثال

public function rules(): array
{
return [
'started_at' => [
'required',
'date',
'force_remote',
'after_or_equal:today',
],
'expired_at' => [
'nullable',
'date',
'force_remote',
'after:started_at',
],
];
}

نکته مهم

force_remote خودش rule بیزینسی نیست.
این فقط به FormValidation می‌گوید validation این فیلد را از backend بپرسد.

برای custom rule، exists و unique معمولا force_remote لازم نیست. این ruleها در حالت عادی هم سمت سرور بررسی می‌شوند.

پس force_remote را زمانی اضافه کنید که ruleهای ساده و قابل اجرای سمت JavaScript هم باید از backend validate شوند.

no_form_validation

اگر می‌خواهید یک فیلد در validation سمت فرم نادیده گرفته شود، از no_form_validation در ruleهای همان فیلد استفاده کنید.

public function rules(): array
{
return [
'description' => [
'nullable',
'string',
'max:5000',
'no_form_validation'
],
];
}

اثر این rule چیست؟

  • validation سمت فرم برای آن فیلد ساخته نمی‌شود
  • validation سمت سرور در submit نهایی همچنان برقرار می‌ماند

چه زمانی استفاده شود؟

  • وقتی کامپوننت رفتار خیلی خاص یا داینامیک دارد و validation سمت فرم برایش مناسب نیست
  • وقتی بررسی خطا باید فقط در submit نهایی انجام شود
  • وقتی ruleهای فیلد برای نمایش زنده UX خوبی ایجاد نمی‌کنند

درباره no_validate

چیزی که در ruleهای FormRequest باید استفاده شود no_form_validation است.
اگر جایی با عنوان no_validate یا نام‌های مشابه برخورد کردید، آن را API اصلی این feature در نظر نگیرید.

disable_validation_cache

disable_validation_cache را داخل ruleهای همان فیلد بگذارید وقتی نمی‌خواهید نتیجه validation آن فیلد cache شود.

رفتار پیش‌فرض FormValidation این است که اگر یک فیلد با یک مقدار مشخص یک‌بار validate شد، در بررسی بعدی با همان مقدار دوباره request یا validation تکراری اجرا نشود.
این rule آن رفتار را برای همان فیلد غیرفعال می‌کند.

دقیقا چه چیزی را عوض می‌کند؟

  • cache نتیجه validation برای همان field را غیرفعال می‌کند
  • باعث می‌شود اگر همان مقدار دوباره بررسی شد، validation از cache قبلی استفاده نکند
  • برای فیلدهای وابسته و dynamic باعث می‌شود re-validation واقعا دوباره اجرا شود

چه زمانی استفاده شود؟

  • وقتی اعتبار یک فیلد به فیلدهای دیگر فرم وابسته است
  • وقتی با تغییر یک فیلد دیگر باید همین فیلد با همان مقدار قبلی دوباره بررسی شود
  • وقتی component یا flow فرم باعث می‌شود تکیه به cache نتیجه validation درست نباشد

مثال

public function rules(): array
{
return [
'expired_at' => [
'nullable',
'force_remote',
'disable_validation_cache',
'after:started_at',
],
];
}

چه زمانی لازم نیست؟

  • برای inputهای ساده و مستقل
  • وقتی وابستگی بین فیلدها ندارید
  • وقتی تکرار نشدن validation برای همان مقدار، رفتار مطلوب شماست

چه چیزهایی معمولا دستی استفاده نمی‌شوند؟

این موارد معمولا جزو استفاده مستقیم در فرم‌ها نیستند:

  • ignore-validation
  • payloadهای داخلی FormValidation
  • fieldهای متادیتای داخلی request

در اغلب فرم‌ها همین‌ها کافی‌اند:

  • ruleهای معمول Laravel
  • force_remote فقط وقتی ruleهای ساده هم باید از backend بررسی شوند
  • no_form_validation
  • disable_validation_cache فقط برای فیلدهایی که نباید از cache نتیجه validation استفاده کنند

پیشنهاد عملی

برای هر فیلد این تصمیم ساده را بگیرید:

  1. اگر rule عادی است، فقط همان ruleهای Laravel را بنویسید.
  2. اگر rule custom، exists یا unique دارید، معمولا نیازی نیست برای remote شدن چیزی اضافه کنید.
  3. اگر ruleهای ساده هم باید حتما از backend بررسی شوند، force_remote را اضافه کنید.
  4. اگر نمی‌خواهید validation سمت فرم برای آن فیلد فعال باشد، no_form_validation را اضافه کنید.
  5. اگر نتیجه validation یک فیلد نباید cache شود، disable_validation_cache را اضافه کنید.

نمونه کامل

FormRequest
public function rules(): array
{
return [
'role_id' => ['required', Rule::exists(Role::class, 'id')],
'started_at' => ['required', 'date', 'force_remote', 'after_or_equal:today'],
'expired_at' => ['nullable', 'date', 'force_remote', 'disable_validation_cache', 'after:started_at'],
'role_period' => ['required', new RoleDateOverlapRule($this->user)],
'note' => ['nullable', 'string', 'max:1000', 'no_form_validation'],
];
}

جمع‌بندی

  • منبع اصلی validation همان FormRequest است
  • custom ruleها و ruleهای دیتابیسی مثل exists و unique به صورت پیش‌فرض remote validate می‌شوند
  • force_remote یعنی ruleهای ساده این فیلد هم از سمت backend بررسی شوند
  • no_form_validation یعنی برای این فیلد validation سمت فرم ساخته نشود
  • disable_validation_cache یعنی نتیجه validation این فیلد cache نشود و بررسی تکراری با همان مقدار دوباره اجرا شود