Search code examples
phplaravellaravel-validation

Laravel Complex Conditional Validation


I'm trying to create a validator that require at least one of three input.

I tried this

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'
   ]);
}

But it was was forcing only the first field (url). So I tried with Complex Conditional Validation.

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;
}

But still no luck... Now it's never required I can submit all three empty field and it's working...

Any clues to help me please ?

Thank you !


Solution

  • You code is working fine. you just forget to check if validate pass or not. because when you use Validator::make you need to manually check it. for request()->validate laravel will do it for you. inside your validateFundingSource () function just check it pass validate or not before return like this:

    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
            }
        }
    

    also sorry for my bad English & hope it help