trait AvoidDuplicateConstraintSoftDelete
{
public static function bootAvoidDuplicateConstraintSoftDelete()
{
static::observe(app(UniqueSoftDeleteObserver::class));
}
public function getDuplicateAvoidColumns() : array
{
return [];
}
}
class UniqueSoftDeleteObserver
{
private const DELIMITER = '-#-';
public function restoring(Model $model)
{
if (!$model->trashed()) {
return;
}
foreach ($model->getDuplicateAvoidColumns() as $column) {
if ($value = (explode(self::DELIMITER, $model->{$column})[1] ?? null)) {
$model->{$column} = $value;
}
}
}
public function deleted(Model $model)
{
if (!$model->isForceDeleting()) {
self::mutateColumns($model);
}
}
public static function mutateColumns(Model $model)
{
foreach ($model->getDuplicateAvoidColumns() as $column) {
if (!empty($model->{$column})) {
$newValue = uniqid() . self::DELIMITER . $model->{$column};
$model->{$column} = $newValue;
}
}
$model->save();
}
public static function restoreColumns(Model $model)
{
if (!$model->trashed()) {
return;
}
foreach ($model->getDuplicateAvoidColumns() as $column) {
if ($value = (explode(self::DELIMITER, $model->{$column})[1] ?? null)) {
$model->{$column} = $value;
}
}
$model->save();
}
}
than in your model:
class User extends Model
{
use HasFactory,
SoftDeletes,
AvoidDuplicateConstraintSoftDelete;
public function getDuplicateAvoidColumns(): array
{
return [
'email',
];
}
now each column defined in getDuplicateAvoidColumns will be mutated to avoid unique constraints, and on restore it will be mutated back to it's original value.