ariaceleste's avatar

After Validation Hook

I've spent the day researching validations and am working with a use case that I believe calls for an after validation hook.

The use case is: Upon submitting the form, the initial validation ensures that my numerical inputs are positive integers. The after validation hook then sums those inputs and ensures they do not equal 100.

In my controller:

            	$validator = Validator::make($request->all(), [
                    'num1' => ['required', 'integer', 'gte:0'],
                    'num2' => ['required', 'integer', 'gte:0'],
                    'num3' => ['required', 'integer', 'gte:0'],
                ])->validate();

                $validator->after(function ($validator) {
                    if ($this->get('num1') + $this->get('num2') + $this->get('num3') != 100) {         
                        $validator->errors()->add(
                            null, 'Something is wrong with this field!'
                        );
                    }
                });

I have rejigged my code to follow https://laravel.com/docs/8.x/validation#after-validation-hook exactly, but I'm getting the error: Call to a member function after() on array.

Thank you in advance.

0 likes
5 replies
Brandon Eichhorn's avatar
Level 4

The docs state that you have to call after() on a validator instance, and you already tried to validate it and therefore retrieve a response.

In short: remove validate() to fix it.

			$validator = Validator::make($request->all(), [
                    'num1' => ['required', 'integer', 'gte:0'],
                    'num2' => ['required', 'integer', 'gte:0'],
                    'num3' => ['required', 'integer', 'gte:0'],
                ]);

                $validator->after(function ($validator) {
                    if ($this->get('num1') + $this->get('num2') + $this->get('num3') != 100) {         
                        $validator->errors()->add(
                            null, 'Something is wrong with this field!'
                        );
                    }
                });
ariaceleste's avatar

Thanks @brandon eichhorn . That certainly fixed it....but now I don't get to take advantage of the redirect. I tried putting $validator->validate(); at the end of the above, but no dice.

I'm also looking for the best way to get the data out of $validator since the $this->get('numx') doesn't work. Any ideas?

1 like
ariaceleste's avatar

@brandon eichhorn Since you were kind enough to respond, I'll close this thread with my solution in case anyone needs it for posterity.

                $validator = Validator::make($request->all(), [
                    'num1' => ['required', 'integer', 'gte:0'],
                    'num2r' => ['required', 'integer', 'gte:0'],
                    'num3' => ['required', 'integer', 'gte:0'],
                    'num4' => ['required', 'integer', 'gte:0'],
                ]);



                $validator->after(function ($validator) {
                    if ($validator->validated('num1') + $validator->validated('num2') +
                    $validator->validated('num3') + $validator->validated('num4')

                    != 100) {
                     
                        
                        $validator->errors()->add(
                            'num1', 'Something is wrong with this field!'
                        );
                    }
                });

                $validator = $validator->validate();

``` 		 		
3 likes
Brandon Eichhorn's avatar

@ariaceleste My apologies, I was looking for a different way of solving it. But I'm glad you've been able to solve it! And you're an absolute hero for posting your solution to help others.

hadi4234's avatar

all of top solutions helped me thanks. however i think some lines could be cleaner.

		... $validator->after(function ($validator) {
               if ($validator->failed()) return;
               if ($request->num1 + $request->num2 +   $request->num3 +
				    $request->num4 != 100){ ...
					} 
  ...     

You could do it also by using form request which is recommended. by using WithValidator method it looks like this:

 class StoreEventRequest extends FormRequest
 {
  public function authorize(): bool
{
    return true;
}

public function rules()
{
    return [
                'num1' => ['required', 'integer', 'gte:0'],
                'num2r' => ['required', 'integer', 'gte:0'],
                'num3' => ['required', 'integer', 'gte:0'],
                'num4' => ['required', 'integer', 'gte:0'],
    ];
}

public function withValidator($validator)
{
    $validator->after(function ($validator) {

        // Skip if any previous field was invalid.
       if ($validator->failed()) return;

        if ($this->num1 + $this->num2 +  request()->num3 +
			    $this->num4 != 100){ 
						
						$validator->errors()->add(
                        'num1', 'Something is wrong with this field!'
                    );
				} 
        });
    }
}

Please or to participate in this conversation.