Skip to content

Instantly share code, notes, and snippets.

@snipe
Last active September 27, 2023 05:11
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save snipe/e9143499d75fd6dce7031497d619a966 to your computer and use it in GitHub Desktop.
Save snipe/e9143499d75fd6dce7031497d619a966 to your computer and use it in GitHub Desktop.
<?php
/*
* Use Case:
* You have multiple deleted_at items that share an attribute that is supposed to be unique,
* for example, a username in a user's table, and are using model-level validation and watson/validation
*
* In this use case, you want to ignore ALL deleted items when considering uniqueness.
*
* The current `unique` validation rule doesn't seem to do this, even when you add the extra
* columns and ignored fields, e.g.:
*
* 'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
*
* Let's say our username is 'snipe'.
*
* If you have ONE deleted user with the username 'snipe', this will pass validation.
*
* If you have MORE THAN ONE deleted user with the username 'snipe', this will fail validation
* disallowing any new user's with that username to be saved. This is obviously a problem, since
* that user will never be able to be saved since it inherently breaks Laravel's built-in
* `unique` validation.
*
* Using this custom validator, we would use this as the validation rule:
*
* 'username' => 'required|string|min:2|unique_undeleted',
*
* where the field following `unique_undeleted:` is the table name we should be querying
* the attribute name against.
*
* This code would go in the AppServiceProvider, in the `boot()` method.
*
* You'll need to add an entry into the `validation.php` language file, like:
* "unique_undeleted" => "The :attribute must be unique.",
*
*/
// In AppServiceProvider.php
Validator::extend('unique_undeleted', function($attribute, $value, $parameters, $validator) {
$count = DB::table($parameters[0])->select('id')->where($attribute,'=',$value)->whereNull('deleted_at')->where('id','!=',$parameters[1])->count();
if ($count < 1) {
return true;
} else {
return false;
}
});
// In app/Http/Traits/UniqueUndeletedTrait.php
<?php
namespace App\Http\Traits;
trait UniqueUndeletedTrait
{
/**
* Prepare a unique_ids rule, adding a model identifier if required.
*
* @param array $parameters
* @param string $field
* @return string
*/
protected function prepareUniqueUndeletedRule($parameters, $field)
{
// Only perform a replacement if the model has been persisted.
if ($this->exists) {
return 'unique_undeleted:'.$this->table.','. $this->getKey();
}
return 'unique_undeleted:'.$this->table.',0';
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment