Laravel Комплексная условная проверка - PullRequest
2 голосов
/ 11 марта 2020

Я пытаюсь создать валидатор, который требует как минимум один из трех входных данных.

Я пробовал это

protected function validateFundingSource (): array
{
    return request()->validate([
       'title'       => 'required',
       'description' => 'required',
       'national'       => 'nullable',
       'province'       => Rule::requiredIf(!request('national')),
       'url'            => [
           'required_without_all:phone,email',
           'active_url'
       ],
       'phone'          => [
           'required_without_all:url,email|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im'
       ],
       'email' => [
           'required_without_all:url,phone|email:rfc,dns'
       ],
       'categories' => 'exists:categories,id'
   ]);
}

Но это было форсирование только первого поля (url). Поэтому я попытался с помощью Сложная условная проверка .

protected function validateFundingSource ()
{

    $v = Validator::make(request()->all(), [
            'title'       => 'required',
            'description' => 'required',
            'national'       => 'nullable',
            'categories'     => 'exists:categories,id',
    ]);

    $v->sometimes('province', 'required', function ($input) {
        return ($input->national === null) ;
    });

    $v->sometimes('url', 'required|active_url', function ($input) {
        return (($input->phone === null) && ($input->email === null));
    });

    $v->sometimes('phone', 'required|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im', function ($input) {
        return (($input->url === null) && ($input->email === null));
    });

    $v->sometimes('email', 'required|email:rfc,dns', function ($input) {
        return (($input->url === null) && ($input->phone === null));
    });

    return $v;
}

Но все равно не повезло ... Теперь мне никогда не требуется отправлять все три пустых поля, и оно работает ...

Любые подсказки, чтобы помочь мне, пожалуйста?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 11 марта 2020

Если вы ищете "хотя бы один из" url, phone или email, тогда вы хотите использовать required_without. Это правило означает, что поле является обязательным, если любое из указанных полей отсутствует; required_without_all означает, что это необходимо, когда все указанных полей отсутствуют.

Вы также путаете синтаксис правила, вы должны использовать либо строковый синтаксис, либо массив, либо не оба одновременно .

Возможно, вы захотите улучшить регулярное выражение своего номера телефона; + -. (000-111.9999 #8 не очень хороший номер телефона, но он пройдет проверку. Я бы посоветовал санировать ваше значение, чтобы удалить все, кроме цифр и начального +, а затем использовать лучший шаблон на том, что осталось.

И это просто косметическое изменение c, но вы можете заменить Rule::requiredIf(!request('national')), на простое required_if правило, похожее на другие.

При переходе на проверку запроса формы это будет выглядеть так:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreFundingsource extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Prepare the data for validation.
     *
     * @return void
     */
    protected function prepareForValidation()
    {
        $phone = preg_replace("/[^0-9]/", "", $this->phone);
        if (strpos($this->phone, "+") === 0) {
            $phone = "+$phone";
        }
        $this->merge(["phone"=>$phone]);
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
           'title'       => ['required'],
           'description' => ['required'],
           'national'    => ['nullable'],
           'province'    => ['required_if,national,'],
           'categories'  => ['exists:categories,id']
           'url'         => [
               'required_without:phone,email',
               'active_url'
           ],
           'phone'       => [
               'required_without:url,email',
               'regex:/^\+?1?[2-9][0-9]{5,14}$/'
           ],
           'email'       => [
               'required_without:url,phone',
               'email:rfc,dns'
           ],
       ];
    }
}
2 голосов
/ 11 марта 2020

Ваш код работает нормально. Вы просто забыли проверить, прошел ли валидацию или нет. потому что когда вы используете Validator :: make, вам нужно вручную проверить это. for request () -> validate laravel сделает это за вас. внутри вашей функции validateFundingSource () просто проверьте ее, передайте validate или нет, прежде чем возвращать, как это:

private function validateFundingSource () {
        $v = Validator::make(request()->all(), [
                'title'       => 'required',
                'description' => 'required',
                'national'       => 'nullable',
                'categories'     => 'exists:categories,id',
        ]);

        $v->sometimes('province', 'required', function ($input) {
            return ($input->national === null) ;
        });

        $v->sometimes('url', 'required|active_url', function ($input) {
            return (($input->phone === null) && ($input->email === null));
        });

        $v->sometimes('phone', 'required|regex:/^(\+\s?)?1?\-?\.?\s?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}(?: *#(\d+))?\s*$/im', function ($input) {
            return (($input->url === null) && ($input->email === null));
        });

        $v->sometimes('email', 'required|email:rfc,dns', function ($input) {
            return (($input->url === null) && ($input->phone === null));
        });

        // check if validae failed
        if($v->fails()) {
            dd('fail', $v); // do something when it failed
        }
    }

также извините за мой плохой Engli sh и надеюсь, что это поможет

...