Last active
September 28, 2020 14:43
-
-
Save afiqiqmal/f7c5ce5fba4d04632098b0356c321803 to your computer and use it in GitHub Desktop.
Laravel SoftDeletesBoolean
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Providers; | |
use Illuminate\Support\ServiceProvider; | |
class BlueprintMacroProvider extends ServiceProvider | |
{ | |
/** | |
* Bootstrap the application services. | |
* | |
* @return void | |
*/ | |
public function boot() | |
{ | |
Blueprint::macro('softDeletesBoolean', function ($dateColumn = 'deleted_at', $column = 'is_deleted') { | |
$this->softDeletes($dateColumn)->index(); | |
$this->boolean($column)->default(0)->index(); | |
}); | |
Blueprint::macro('dropSoftDeletesBoolean', function ($dateColumn = 'deleted_at', $column = 'is_deleted') { | |
$this->dropSoftDeletes($dateColumn); | |
$this->boolean($column)->default(0)->index(); | |
}); | |
} | |
/** | |
* Register the application services. | |
* | |
* @return void | |
*/ | |
public function register() | |
{ | |
// | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models\Traits; | |
use App\Models\Scopes\SoftDeletingBooleanScope; | |
use Illuminate\Database\Eloquent\SoftDeletes; | |
/** | |
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withTrashed() | |
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder onlyTrashed() | |
* @method static static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder withoutTrashed() | |
*/ | |
trait SoftDeletesBoolean | |
{ | |
use SoftDeletes; | |
/** | |
* Indicates if the model is currently force deleting. | |
* | |
* @var bool | |
*/ | |
protected $forceDeleting = false; | |
/** | |
* Boot the soft deleting trait for a model. | |
* | |
* @return void | |
*/ | |
public static function bootSoftDeletes() | |
{ | |
} | |
/** | |
* Boot the soft deleting trait for a model. | |
* | |
* @return void | |
*/ | |
public static function bootSoftDeletesBoolean() | |
{ | |
static::addGlobalScope(new SoftDeletingBooleanScope()); | |
} | |
/** | |
* Force a hard delete on a soft deleted model. | |
* | |
* @return bool|null | |
*/ | |
public function forceDelete() | |
{ | |
$this->forceDeleting = true; | |
$deleted = $this->delete(); | |
$this->forceDeleting = false; | |
return $deleted; | |
} | |
/** | |
* Perform the actual delete query on this model instance. | |
* | |
* @return mixed | |
*/ | |
protected function performDeleteOnModel() | |
{ | |
if ($this->forceDeleting) { | |
$this->exists = false; | |
return $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey())->forceDelete(); | |
} | |
return $this->runSoftDelete(); | |
} | |
/** | |
* Perform the actual delete query on this model instance. | |
* | |
* @return void | |
*/ | |
protected function runSoftDelete() | |
{ | |
$query = $this->newQueryWithoutScopes()->where($this->getKeyName(), $this->getKey()); | |
$time = $this->freshTimestamp(); | |
$columns = [ | |
$this->getIsDeletedColumn() => 1, | |
$this->getDeletedAtColumn() => $this->fromDateTime($time) | |
]; | |
$this->{$this->getIsDeletedColumn()} = 1; | |
$this->{$this->getDeletedAtColumn()} = $time; | |
if ($this->timestamps && ! is_null($this->getUpdatedAtColumn())) { | |
$this->{$this->getUpdatedAtColumn()} = $time; | |
$columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time); | |
} | |
$query->update($columns); | |
} | |
/** | |
* Restore a soft-deleted model instance. | |
* | |
* @return bool|null | |
*/ | |
public function restore() | |
{ | |
// If the restoring event does not return false, we will proceed with this | |
// restore operation. Otherwise, we bail out so the developer will stop | |
// the restore totally. We will clear the deleted timestamp and save. | |
if ($this->fireModelEvent('restoring') === false) { | |
return false; | |
} | |
$this->{$this->getIsDeletedColumn()} = 0; | |
$this->{$this->getDeletedAtColumn()} = null; | |
// Once we have saved the model, we will fire the "restored" event so this | |
// developer will do anything they need to after a restore operation is | |
// totally finished. Then we will return the result of the save call. | |
$this->exists = true; | |
$result = $this->save(); | |
$this->fireModelEvent('restored', false); | |
return $result; | |
} | |
/** | |
* Determine if the model instance has been soft-deleted. | |
* | |
* @return bool | |
*/ | |
public function trashed() | |
{ | |
return (bool)$this->{$this->getIsDeletedColumn()}; | |
} | |
/** | |
* Register a restoring model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function restoring($callback) | |
{ | |
static::registerModelEvent('restoring', $callback); | |
} | |
/** | |
* Register a restored model event with the dispatcher. | |
* | |
* @param \Closure|string $callback | |
* @return void | |
*/ | |
public static function restored($callback) | |
{ | |
static::registerModelEvent('restored', $callback); | |
} | |
/** | |
* Determine if the model is currently force deleting. | |
* | |
* @return bool | |
*/ | |
public function isForceDeleting() | |
{ | |
return $this->forceDeleting; | |
} | |
/** | |
* Get the name of the "deleted at" column. | |
* | |
* @return string | |
*/ | |
public function getIsDeletedColumn() | |
{ | |
return defined('static::IS_DELETED') ? static::IS_DELETED : 'is_deleted'; | |
} | |
/** | |
* Get the fully qualified "deleted at" column. | |
* | |
* @return string | |
*/ | |
public function getQualifiedIsDeletedColumn() | |
{ | |
return $this->getTable().'.'.$this->getIsDeletedColumn(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Models\Scopes; | |
use Illuminate\Database\Eloquent\Builder; | |
use Illuminate\Database\Eloquent\Model; | |
use Illuminate\Database\Eloquent\SoftDeletingScope; | |
class SoftDeletingBooleanScope extends SoftDeletingScope | |
{ | |
/** | |
* All of the extensions to be added to the builder. | |
* | |
* @var array | |
*/ | |
protected $extensions = ['Restore', 'WithTrashed', 'WithoutTrashed', 'OnlyTrashed']; | |
/** | |
* Apply the scope to a given Eloquent query builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @param \Illuminate\Database\Eloquent\Model $model | |
* @return void | |
*/ | |
public function apply(Builder $builder, Model $model) | |
{ | |
$builder->where($model->getQualifiedIsDeletedColumn(), 0); | |
} | |
/** | |
* Extend the query builder with the needed functions. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @return void | |
*/ | |
public function extend(Builder $builder) | |
{ | |
foreach ($this->extensions as $extension) { | |
$this->{"add{$extension}"}($builder); | |
} | |
$builder->onDelete(function (Builder $builder) { | |
$column = $this->getIsDeletedColumn($builder); | |
return $builder->update([ | |
$column => 1, | |
]); | |
}); | |
} | |
/** | |
* Get the "deleted at" column for the builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @return string | |
*/ | |
protected function getIsDeletedColumn(Builder $builder) | |
{ | |
if (count((array) $builder->getQuery()->joins) > 0) { | |
return $builder->getModel()->getQualifiedIsDeletedColumn(); | |
} | |
return $builder->getModel()->getIsDeletedColumn(); | |
} | |
/** | |
* Add the restore extension to the builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @return void | |
*/ | |
protected function addRestore(Builder $builder) | |
{ | |
$builder->macro('restore', function (Builder $builder) { | |
$builder->withTrashed(); | |
return $builder->update([$builder->getModel()->getIsDeletedColumn() => 0]); | |
}); | |
} | |
/** | |
* Add the with-trashed extension to the builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @return void | |
*/ | |
protected function addWithTrashed(Builder $builder) | |
{ | |
$builder->macro('withTrashed', function (Builder $builder) { | |
return $builder->withoutGlobalScope($this); | |
}); | |
} | |
/** | |
* Add the without-trashed extension to the builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @return void | |
*/ | |
protected function addWithoutTrashed(Builder $builder) | |
{ | |
$builder->macro('withoutTrashed', function (Builder $builder) { | |
$model = $builder->getModel(); | |
$builder->withoutGlobalScope($this)->where( | |
$model->getQualifiedIsDeletedColumn(),0 | |
); | |
return $builder; | |
}); | |
} | |
/** | |
* Add the only-trashed extension to the builder. | |
* | |
* @param \Illuminate\Database\Eloquent\Builder $builder | |
* @return void | |
*/ | |
protected function addOnlyTrashed(Builder $builder) | |
{ | |
$builder->macro('onlyTrashed', function (Builder $builder) { | |
$model = $builder->getModel(); | |
$builder->withoutGlobalScope($this)->where( | |
$model->getQualifiedIsDeletedColumn(), 1 | |
); | |
return $builder; | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment