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
и попытались отправить форму:
И если выбран статус 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
проверяемое поле должно присутствовать и быть не пустым только в том случае, если какое-либо из других указанных поле присутствует и не пустое.
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'],
];
}
Дополнительную информацию я о всех условных правилах валидации можно найти в официальной документации.