Search code examples
phplaravellaravel-5laravel-5.5laravel-validation

Required field only if another field has a value, must be empty otherwise


My question is about Laravel validation rules.

I have two inputs a and b. a is a select input with three possible values: x, y and z. I want to write this rule:

b must have a value only if a values is x. And b must be empty otherwise.

Is there a way to write such a rule? I tried required_with, required_without but it seems it can not cover my case.

In other words, if the previous explanation was not clear enough:

  • If a == x, b must have a value.
  • If a != x, b must be empty.

Solution

  • You have to create your own validation rule.

    Edit app/Providers/AppServiceProvider.php and add this validation rule to the boot method:

    // Extends the validator
    \Validator::extendImplicit(
        'empty_if',
        function ($attribute, $value, $parameters, $validator) {
            $data = request()->input($parameters[0]);
            $parameters_values = array_slice($parameters, 1);
            foreach ($parameters_values as $parameter_value) {
                if ($data == $parameter_value && !empty($value)) {
                    return false;
                }
            }
            return true;
        });
    
    // (optional) Display error replacement
    \Validator::replacer(
        'empty_if',
        function ($message, $attribute, $rule, $parameters) {
            return str_replace(
                [':other', ':value'], 
                [$parameters[0], request()->input($parameters[0])], 
                $message
            );
        });
    

    (optional) Create a message for error in resources/lang/en/validation.php:

    'empty_if' => 'The :attribute field must be empty when :other is :value.',
    

    Then use this rule in a controller (with require_if to respect both rules of the original post):

    $attributes = request()->validate([
        'a' => 'required',
        'b' => 'required_if:a,x|empty_if:a,y,z'
    ]);
    

    It works!

    Side note: I will maybe create a package for this need with empty_if and empty_unless and post the link here