Проверка полей условно с помощью Laravel

У меня есть следующие правила проверки для Laravel:

return [
    'offer_type' => 'required|in:permanent,temporary',
    'start_date' => 'required_if:offer_type,temporary|date_format:d/m/Y',
    'end_date' => 'required_if:offer_type,temporary|date_format:d/m/Y|after:start_date',
];

В основном, если offer_type является temporary, start_date а также end_date требуется и должен следовать d/m/Y формат. Так же end_date должно быть после start_date,

Если offerType является permanentнет необходимости подтверждать start_date или же end_date так как они даже не используются.

Проблема у меня заключается в том, что, если пользователь отправляет данные следующим образом:

  • offerType: постоянный
  • startDate: foo
  • endDate: бар

Тогда Laravel выдаст ошибку проверки, даже если start_date а также end_date не требует проверки, так как тип предложения permanent,

Как я могу сделать так, чтобы Laravel только проверял start_date а также end_date если offer_type является temporary,

Мое (плохое) решение

Единственный способ найти эту проблему - сделать следующее:

Измените приведенные выше правила проверки на следующее:

return [
    'offer_type' => 'required|in:permanent,temporary',
    'start_date' => 'required_if:offer_type,temporary',
    'end_date' => 'required_if:offer_type,temporary',
];

и добавьте следующий код в валидатор:

$validator->after(function (Validator $validator) {
    $data = $validator->getData();
    $failed = $validator->failed();

    if (array_key_exists('offerType', $data) &&
        $data['offerType'] === 'temporary' &&
        array_key_exists('start_date', $data) &&
        array_key_exists('end_date', $data) &&
        !array_key_exists('start_date', $failed) &&
        !array_key_exists('end_date', $failed)
    ) {
        $startDateString = $data['start_date'];
        $endDateString = $data['end_date'];

        $startDate = Carbon::createFromFormat('d/m/Y', $startDateString);
        $endDate = Carbon::createFromFormat('d/m/Y', $endDateString);

        if ($startDate === false) {
            $validator->errors()->add('start_date', 'Start date must be in the format "dd/mm/yyyy"');
        }

        if ($endDate === false) {
            $validator->errors()->add('end_date', 'End date must be in the format "dd/mm/yyyy"');
        }

        if ($startDate !== false && $endDate !== false && $endDate->lt($startDate)) {
            $validator->errors()->add('end_date', 'End date must be after or equal to the start date');
        }
    }
});

1 ответ

Я бы предложил вам иметь отдельный класс FormRequest. Тогда ваш rules() будет выглядеть так:

public function rules()
{
    $rules = [
        'offer_type' => 'required|in:permanent,temporary',
        'start_date' => 'required_if:offer_type,temporary',
        'end_date' => 'required_if:offer_type,temporary',
    ];

    if ($this->offer_type == 'permament') {
        $this->getInputSource()->remove('start_date'); // optionally you may remove start_date from request
        $this->getInputSource()->remove('end_date');  // same of end_date
        unset($rules['start_date']); 
        unset($rules['end_date']);
    }

    return $rules;
}

Документы Laravel о проверке формы запроса

Другие вопросы по тегам