6

Below is a snippet of my validation currently:

'independent_financial_advisor' => 'required|boolean',
'understand_objective' => 'required|boolean',
'confirm_objective' => 'required|boolean',
'understand_term_held' => 'required|boolean',
'tax_relief' => 'required|boolean',

I need to validate that when independent_financial_advisor is false, the remaining 4 fields below must be true. I could not find any Laravel rule which could do this so I thought about using a closure to create a custom rule.

The issue with this is that I don't know how to reference another field in a closure to check its value.

What is the best way to go about this? Thanks

Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
Gazz
  • 1,017
  • 3
  • 17
  • 31
  • 1
    Seems this ought to be useful? https://stackoverflow.com/questions/28793716/how-add-custom-validation-rules-when-using-form-request-validation-in-laravel-5?rq=1 – Nick Dec 14 '18 at 12:13
  • @Nick Came across it before but after re-reading it, i've managed to get this to work with my form. Many thanks. – Gazz Dec 14 '18 at 12:55

6 Answers6

6

I added a custom validation rule called true_if_reference_is_false and passed a parameter to it which is independent_financial_advisor.

So the validation looks like this:

$this->validate($request, [
    'independent_financial_advisor' => 'required|boolean',
    'understand_objective' => 'required|boolean|true_if_reference_is_false:independent_financial_advisor',
    'confirm_objective' => 'required|boolean|true_if_reference_is_false:independent_financial_advisor',
    'understand_term_held' => 'required|boolean|true_if_reference_is_false:independent_financial_advisor',
    'tax_relief' => 'required|boolean|true_if_reference_is_false:independent_financial_advisor'
]);

You need to define this validation rule in App\Providers\AppServiceProvider.php Import Facade Validator.

use Illuminate\Support\Facades\Validator;

And define the rule in the boot method:

Validator::extend('true_if_reference_is_false', function ($key, $value, $parameters, $validator) {
    $request = request();
    $keyReference = $parameters[0];
    if ($request->has($parameters[0]) && $request->$keyReference == false)
        return (bool)$request->$key;
    else
        return true;
});

Hope this helps :)

cfnerd
  • 3,658
  • 12
  • 32
  • 44
Sadegh Ameri
  • 312
  • 1
  • 8
4
'independent_financial_advisor' => 'required|boolean',
'understand_objective' => 'boolean|required_if:independent_financial_advisor,0,false',
'confirm_objective' => 'boolean|required_if:independent_financial_advisor,0,false',
'understand_term_held' => 'boolean|required_if:independent_financial_advisor,0,false',
'tax_relief' => 'boolean|required_if:independent_financial_advisor,0,false',

For more validation rules, check laravel documentation here https://laravel.com/docs/5.7/validation#rule-required-if

  • 1
    Sorry if I've got this wrong but required_if just ensures that the field is required. My four fields are always required regardless of if its value is true or false. – Gazz Dec 14 '18 at 12:54
4
$validator = Validator::make($request->all(), [
                'tax_relief'=>['required','in:true']
            ]);
if ($validator->fails()) {
                return response()->json($validator->errors());
}
Ausra
  • 41
  • 2
1

Using Laravel 8, I solved this with the following:

// MyFormRequest.php
public function rules()
{
    return [
        'bool_attrib_1' => [
            'required',
            'bool',
            function ($attribute, $value, $fail) {
                if (! $value && ! request('bool_attrib_2')) {
                    $fail('You must select either Bool Attrib 1 or Bool Attrib 2.');
                }
            },
        ],
        'bool_attrib_2' => [
            'required',
            'bool',
            function ($attribute, $value, $fail) {
                if (! $value && ! request('bool_attrib_1')) {
                    $fail('You must select either Bool Attrib 1 or Bool Attrib 2.');
                }
            },
        ],
    ];
}
tptcat
  • 3,894
  • 2
  • 32
  • 51
0

I came across this problem today and solved it with a conditional validation closure (as it's only used once throughout the app).

Basically the user must mark either the phone or email field as required. They can both be true or only one can be true, but the cannot both be false.

The trick is to use the request object in the closure to gain access to the other field that needs to be part of the validation check. The fields are part of an array casted property, that's why it has the .'s.

           'required_order_fields.phone' => [
                Rule::in(["true", "false"]),
                function ($attribute, $value, $fail) use ($request) {
                    if ($value === "false" && $request->input('required_order_fields.email') === "false") {
                        $fail('The '.$attribute.' must be required if the email customer field is not required');
                    }
                },
            ],
            'required_order_fields.email' => [
                Rule::in(["true", "false"]),
                function ($attribute, $value, $fail) use ($request) {
                    if ($value === "false" && $request->input('required_order_fields.phone') === "false") {
                        $fail('The '.$attribute.' must be required if the phone customer field is not required');
                    }
                },
            ],
0
    Validator::extend('true_if_reference_is_false', function ($key, $value, $parameters, $validator) {
        $request = request();
        $keyReference = $parameters[0];
        if ($request->has($parameters[0]) && $request->$keyReference == false)
            return (bool)$request->$key;
        else
            return true;
    });

    Validator::extend('false_if_reference_is_true', function ($key, $value, $parameters, $validator) {
        $request = request();
        $keyReference = $parameters[0];
        if ($request->has($parameters[0]) && $request->$keyReference == true)
            return !(bool)$request->$key;
        else
            return true;
    });