1

I'm trying to validate 'parent_code' attr regarding 'level' field value

Here is what i'm trying to achieve :

'parent_code' is only required when 'level' is != 0 (This part works fine)

and when it's set, it must also exists in table 'products' ('product_code' : the column name that will be used)

My current code (doesn't work properly)

Product resource class

public function fields(Request $request) {
        return [
            ID::make()->sortable(),

            Text::make('Product code', 'product_code')
                ->rules('required')
                ->creationRules('unique:products,product_code')
                ->updateRules('unique:products,product_code,{{resourceId}}')->hideFromIndex(),


            Text::make('Product short name', 'product_short_name')->onlyOnForms(), 


            Textarea::make('Product name', 'product_name')
                ->rules('required')
                ->sortable()
                ->onlyOnForms(),

            Text::make('Parent code', 'parent_code')
                ->rules(['required_if:level,2,4,6', 'exists:products,product_code'])
                ->hideFromIndex(), 

            Select::make('Level', 'level')->options([
                '0' => 'Sector level',
                '2' => 'H2',
                '4' => 'H4',
                '6' => 'H6',
            ])->rules('required')->sortable(),    

        ];
}

Create Product Form

Create product form

Thank you for your help.

2
  • Do you need to apply the exists rule only if the required if is satisfied? Commented Feb 10, 2020 at 13:40
  • Exactly, only when required if is satisfied Commented Feb 10, 2020 at 13:42

1 Answer 1

9

The proper way would have been to use the sometimes() method on the validator instance, but you can't access it from Laravel Nova rules.

You can just define the rules as a closure that recieves the current incoming request and check the value to dinamically build the rules array:

Laravel Collections solution

Text::make('Parent code', 'parent_code')
    ->hideFromIndex()
    ->rules(function ($request) {
        // You could also use "->when(...)" instead of "->unless(...)"
        // and invert the condition (first argument)
        return collect(['required_if:level,2,4,6'])
            ->unless($request->level === 0, function ($rules) {
                return $rules->push('exists:products,product_code');
            })
            ->toArray();
    }),

The logic without using collections is the same, just use basic if statements to dynamically add conditions:

Plain PHP Arrays Solution

Text::make('Parent code', 'parent_code')
    ->hideFromIndex()
    ->rules(function ($request) {
        return [
            'required_if:level,2,4,6',
            ($request->level !== 0) ? 'exists:products,product_code' : '',
        ];
    }),

or (variant):

Text::make('Parent code', 'parent_code')
    ->hideFromIndex()
    ->rules(function ($request) {
        $rules = ['required_if:level,2,4,6'];

        if ($request->level !== 0) {
            $rules[] = 'exists:products,product_code';
        }

        return $rules;
    }),
Sign up to request clarification or add additional context in comments.

6 Comments

Thank you for your help and your time, now i'm getting "Method Illuminate\Validation\Validator::validateRequiredIf:level,2,4,6 does not exist."
Which nova version are you using? Also, try to chain ->toArray(); method after the unless call.
i'm using v2.8.0
This works perfectly fine when using $request->level === '0'. Thank you
Since you are using Laravel I proposed you a solution with collections, but if you are more comfortable with normal php arrays just let me know and I'll add a variant of this solution without collections as well.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.