Validate Request Parameter Not Present in Laravel 5.4

You can make use of guarded or fillable attributes in Eloquent models in Laravel to help control what values you might allow to be updated via your API. But, I wanted to go a step further and actually stop certain values from being passed in. You could go pretty wild with this and try to block everything, but that’s not what I did. I made this validator.

This is useful in two ways: first, whenever a field was deprecated and not used, I wanted to invalidate API calls with that value now. All of my clients should have been moved over, but just in case, I wanted to stop the value from coming in. The second way this is valuable is if you want to accept some values in a post, but not in a patch or vice versa. (If you kept validation in request files directly this might not be such a problem, but I opted to share/save my validation on my model to keep this all domain knowledge all in one area.) Anyway, I ramble.

Here’s how you’d validate that a field is not present in Laravel 5.4 (the version is mentioned because the most recent Laravel has a different format of validator.)

app/Validators/NotPresentValidator.php

<?php
/**
 * Validator to test that the value isn't present
 */
declare(strict_types=1);

namespace App\Validators;

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Support\Arr;

/**
 * Class AnyBooleanValueValidator
 * @package App\Validators
 */
class NotPresentValidator
{
  /**
   * This is invoked by the validator rule 'not_present'
   * 
   * @param $attribute string the attribute name that is validating
   * @param $value mixed the value that we're testing
   * @param $parameters array 
   * @param $validator Validator The Validator instance
   * @return bool
   */
  public function validate($attribute, $value, $parameters = [], Validator $validator = null): bool
  {
      return !Arr::has($validator->attributes(), $attribute);
  }
}

This is then registered using extendImplicit on the Validator class in the app service provider:

Validator::extendImplicit('not_present', NotPresentValidator::class);

Extend implicit is needed because we are saying we want to validate on a field that doesn’t exist. If we didn’t do this, it would never check for a field that doesn’t exist - basically a chicken+egg issue. This solves it by running validation on a field whether it exists or not.

Finally, I added an error to the validation language resource file.

resources/lang/en/validation.php

'not_present' => 'The :attribute field should not be present in this request. (It may be deprecated.)',

Return to All Posts