Laravel: Условная валидация

Источник: «Laravel Conditional Validation Based on Other Fields: 4 Examples»
При проверке форм или API запросов иногда правило для одного поля зависит от значений других полей. В этой статье я покажу четыре различных примера синтаксиса Laravel для достижения этой цели.

1. Правило required_if

Допустим, у нас есть следующий сценарий:

Если статус статьи draft, требуется только title, а если статус published, то требуется title и content.

Форма для этого примера имеет следующее содержание:

resources/views/posts/create.blade.php:

<div class="p-6 text-gray-900">
<div class="text-green-600">{{ session('status') }}</div>
<form action="{{ route('posts.store') }}" method="post" class="flex flex-col gap-4">
@csrf
<div class="flex flex-col gap-2">
<label for="title">Title</label>
<input id="title" name="title" type="text" value="{{ old('title') }}" />
@error('title')
<div class="text-red-600">{{ $message }}</div>
@enderror
</div>

<div class="flex flex-col gap-2">
<label for="content">Content</label>
<textarea id="content" name="content">{{ old('content') }}</textarea>
@error('content')
<div class="text-red-600">{{ $message }}</div>
@enderror
</div>

<div class="flex flex-col gap-2">
<label for="status">Status</label>
<select id="status" name="status">
<option value="draft" {{ old('status') == 'draft' ? 'selected' : '' }}>Draft</option>
<option value="published" {{ old('status') == 'published' ? 'selected' : '' }}>Published</option>
</select>
@error('status')
<div class="text-red-600">{{ $message }}</div>
@enderror
</div>

<div>
<button class="px-3 py-2 bg-blue-800 text-white rounded">Submit</button>
</div>
</form>
</div>

Метод контроллера довольно прост:

app/Http/Controllers/PostController.php:

public function store(StorePostRequest $request)
{
Post::create($request->validated());

return to_route('posts.create')->withStatus('Created.');
}

Затем мы можем определить правила валидации следующим образом:

app/Http/Requests/StorePostRequest.php:

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StorePostRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}

public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'content' => ['required_if:status,published'],
'status' => ['required', 'in:draft,published'],
];
}
}

Результат, если мы выбрали статус draft и попытались отправить форму:

Результат отправки формы со статусом Draft

И если выбран статус published:

Результат отправки формы со статусом Published

Правило required_if может принимать гораздо больше условий, формат следующий:

required_if:field,value,field,value...

Подходит, если проверка зависит от значений других полей.

2. Правило required_with

теперь предположим, что нужно заполнить поле имя автора, когда у нас есть какой-либо контент.

Добавим поле author в форму:

resources/views/posts/create.blade.php:

{{-- ... --}}

<div class="flex flex-col gap-2">
<label for="author">Author</label>
<input id="author" name="author" type="text" value="{{ old('author') }}" />
@error('author')
<div class="text-red-600">{{ $message }}</div>
@enderror
</div>

И новое правило валидации:

app/Http/Requests/StorePostRequest.php:

// ...

public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'content' => ['required_if:status,published'],
'status' => ['required', 'in:draft,published'],
'author' => ['required_with:content'],
];
}

Теперь поле author обязательное для заполнения, когда поле content содержит какую-либо информацию, независимо от значения status.

Условная валидация с required_with

При использовании правила required_with проверяемое поле должно присутствовать и быть не пустым только в том случае, если какое-либо из других указанных поле присутствует и не пустое.

3. Метод Rule::when()

Rule::when($condition, $rules, $defaultRules = []) полезно, когда вы хотите добавить правила условно, чтобы разрешить публикацию в рабочее время:

app/Http/Requests/StorePostRequest.php:

 use Illuminate\Validation\Rule;

//...

public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
'content' => ['required_if:status,published'],
'status' => [
'required',
+ Rule::when(
+ now()->between('9:00', '17:00'),
+ 'in:draft,published',
+ 'in:draft'
+ ),
],
'author' => ['required_with:content'],
];
}

4. Метод Rule::requiredIf()

Метод Rule::requiredIf($callable|bool $callback) можно использовать для создания более сложного условия путём добавления собственной логики:

app/Http/Requests/StorePostRequest.php:

 use Illuminate\Validation\Rule;

//...

public function rules(): array
{
return [
'title' => ['required', 'string', 'max:255'],
+ 'content' => [Rule::requiredIf(function () {
+ return $this->input('status') == 'published';
+ })],
'status' => [
'required',
Rule::when(
now()->between('9:00', '17:00'),
'in:draft,published',
'in:draft'
),
],
'author' => ['required_with:content'],
];
}

Дополнительную информацию я о всех условных правилах валидации можно найти в официальной документации.

Дополнительные материалы

Предыдущая Статья

CSS: Введение в контейнерные запросы

Следующая Статья

Три причины изучить Laravel