HorusKol

Fail validation if a parameter is sent regardless of its value in Laravel

October 31, 2020

a no entry sign on a gate
source - license

The Laravel framework has some powerful validation built into it.

One of the most useful features is that after successfully validating input parameters from a request you get an array of only the validated data. Any inputs that are not mentioned in the validation rules are silently removed from this array - ensuring that you are only working with valid data.

I would say that 99.9999% of the time, this is exactly the behaviour you want.

However, yesterday I came upon an unusual situation where I wanted to tell the client (over an API - not a user filled form) that they shouldn't have sent a particular parameter. I couldn't find anything in the documentation that suggested how to do this, so I reached out to the PHP Australia developer community and thanks to a suggestion there I came up with something that was surprisingly easy in hindsight.

Introducing the 'never' rule

Validator::extend('never', function () {
    return false;
}, ':attribute is not an acceptable parameter');

That's (almost) all there is to it. Since this uses the Validator facade, you can put this code almost anywhere (even right before you validate). Personally, I put all this in a ValidatorServiceProvider so that they are all available wherever I need them.

The only other thing is to put the rule into the validator:

$validatedData = $request->validate([
    'want-this-uuid' => 'required|uuid|exists:some_table,uuid',
    'want-this-name' => 'required|string',
    'never-send-this' => 'never',
]);

So long as the request does not send the never-send-this parameter (and the other parameters are valid), the request will pass validation. The $validatedData array won't contain the parameter either since we didn't send it.

If the API client does happen to send the parameter, it will be told off.

Caveats

This is a very unusual case - almost always I want to just silently ignore unexpected parameters (as is the default behaviour) - so I would use this very sparingly.