diff --git a/app/Models/Model.php b/app/Models/Model.php index ccdea0b229cbc2d3f69a49942c9f8fa2c9ef1937..8a5d52f911bf7c07aede88a792f2fb133b6b74df 100644 --- a/app/Models/Model.php +++ b/app/Models/Model.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Models\SoftDelete\SoftDelete; use App\Scopes\DeleteScope; use App\Traits\Instance; use App\Traits\MysqlTable; @@ -10,6 +11,7 @@ use Illuminate\Database\Eloquent\Model as EloquentModel; class Model extends EloquentModel { + use SoftDelete; use MysqlTable; use Instance; use HasFactory; @@ -48,22 +50,6 @@ class Model extends EloquentModel return $this->attributes[self::UPDATED_AT]; } - /** - * 自定义的软删除 - */ - protected $is_delete = 1; //是否开启删除(1.开启删除,就是直接删除;0.假删除) - protected $delete_field = 'is_delete'; //删除字段 - - public function getIsDelete() - { - return $this->is_delete; - } - - public function getDeleteField() - { - return $this->delete_field; - } - /** * 不可批量赋值的属性 * @@ -71,19 +57,6 @@ class Model extends EloquentModel */ protected $guarded = []; - /** - * 模型的 "booted" 方法 - * - * 应用全局作用域 - * - * @return void - */ - protected static function booted() - { - // 假删除的作用域 - static::addGlobalScope(new DeleteScope(new static)); - } - public static function firstByWhere($where) { return self::where($where)->first(); diff --git a/app/Models/SoftDelete/DeleteScope.php b/app/Models/SoftDelete/DeleteScope.php new file mode 100644 index 0000000000000000000000000000000000000000..ff1a32bb68812e7696b6c7b0ec64684e4e44caf4 --- /dev/null +++ b/app/Models/SoftDelete/DeleteScope.php @@ -0,0 +1,143 @@ +getIsDelete() == 0) $builder->where($model->getQualifiedDeletedAtColumn(), $model->getIsDelete()); + } + + /** + * Extend the query builder with the needed functions. + * + * @param \Illuminate\Database\Eloquent\Builder $builder + * @return void + */ + public function extend(Builder $builder) + { + // 假删除时,才需要调用扩展方法与更新字段状态 + if ($builder->getModel()->getIsDelete() == 0){ + foreach ($this->extensions as $extension) { + $this->{"add{$extension}"}($builder); + } + + $builder->onDelete(function (Builder $builder) { + $column = $this->getDeletedAtColumn($builder); + + return $builder->update([ + $column => 1, + ]); + }); + } + } + + /** + * Get the "deleted at" column for the builder. + * + * @param \Illuminate\Database\Eloquent\Builder $builder + * @return string + */ + protected function getDeletedAtColumn(Builder $builder) + { + if (count((array) $builder->getQuery()->joins) > 0) { + return $builder->getModel()->getQualifiedDeletedAtColumn(); + } + + return $builder->getModel()->getDeletedAtColumn(); + } + + /** + * 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()->getDeletedAtColumn() => 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, $withTrashed = true) { + if (! $withTrashed) { + return $builder->withoutTrashed(); + } + + 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->getQualifiedDeletedAtColumn(), 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->getQualifiedDeletedAtColumn(), 0); + + return $builder; + }); + } +} diff --git a/app/Models/SoftDelete/SoftDelete.php b/app/Models/SoftDelete/SoftDelete.php new file mode 100644 index 0000000000000000000000000000000000000000..09807b727039df38f0b9a4347714dd516dc55199 --- /dev/null +++ b/app/Models/SoftDelete/SoftDelete.php @@ -0,0 +1,194 @@ +is_delete; + } + + public function getDeleteField() + { + return static::DELETE_FIELD; + } + + /** + * Boot the soft deleting trait for a model. + * + * @return void + */ + public static function bootSoftDelete() + { + static::addGlobalScope(new DeleteScope()); + } + + /** + * Force a hard delete on a soft deleted model. + * + * @return bool|null + */ + public function forceDelete() + { + $this->is_delete = 1; + + return tap($this->delete(), function ($deleted) { + $this->is_delete = 0; + + if ($deleted) { + $this->fireModelEvent('forceDeleted', false); + } + }); + } + + /** + * Perform the actual delete query on this model instance. + * + * @return mixed + */ + protected function performDeleteOnModel() + { + if ($this->is_delete) { + $this->exists = false; + + return $this->setKeysForSaveQuery($this->newModelQuery())->forceDelete(); + } + + return $this->runSoftDelete(); + } + + /** + * Perform the actual delete query on this model instance. + * + * @return void + */ + protected function runSoftDelete() + { + $query = $this->setKeysForSaveQuery($this->newModelQuery()); + + $time = $this->freshTimestamp(); + + $columns = [$this->getDeletedAtColumn() => 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); + + $this->syncOriginalAttributes(array_keys($columns)); + + $this->fireModelEvent('trashed', false); + } + + /** + * 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->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 ! is_null($this->{$this->getDeletedAtColumn()}); + } + + /** + * Register a "softDeleted" model event callback with the dispatcher. + * + * @param \Closure|string $callback + * @return void + */ + public static function softDeleted($callback) + { + static::registerModelEvent('trashed', $callback); + } + + /** + * Register a "restoring" model event callback with the dispatcher. + * + * @param \Closure|string $callback + * @return void + */ + public static function restoring($callback) + { + static::registerModelEvent('restoring', $callback); + } + + /** + * Register a "restored" model event callback with the dispatcher. + * + * @param \Closure|string $callback + * @return void + */ + public static function restored($callback) + { + static::registerModelEvent('restored', $callback); + } + + /** + * Register a "forceDeleted" model event callback with the dispatcher. + * + * @param \Closure|string $callback + * @return void + */ + public static function forceDeleted($callback) + { + static::registerModelEvent('forceDeleted', $callback); + } + + /** + * Get the name of the "deleted at" column. + * + * @return string + */ + public function getDeletedAtColumn() + { + return defined('static::DELETED_AT') ? static::DELETED_FIELD : 'is_delete'; + } + + /** + * Get the fully qualified "deleted at" column. + * + * @return string + */ + public function getQualifiedDeletedAtColumn() + { + return $this->qualifyColumn($this->getDeletedAtColumn()); + } +} diff --git a/app/Modules/Admin/Services/BaseService.php b/app/Modules/Admin/Services/BaseService.php index 891528e5104dddeb8d85dc83ecdc390639343317..c3de2cab08a03dc7161ed0789998d45b56192612 100644 --- a/app/Modules/Admin/Services/BaseService.php +++ b/app/Modules/Admin/Services/BaseService.php @@ -110,11 +110,7 @@ class BaseService extends Service if ($this->model instanceof MonthModel && isset($params['month'])){ $this->model = $this->model->setMonthTable($params['month']); } - if ($this->model->getIsDelete() == 0){ - return $this->model->whereIn($primaryKey, $ids)->update([$this->model->getDeleteField() => 1]); - }else{ - return $this->model->whereIn($primaryKey, $ids)->delete(); - } + return $this->model->whereIn($primaryKey, $ids)->delete(); } /** diff --git a/app/Modules/Bbs/Resources/views/layouts/master.blade.php b/app/Modules/Bbs/Resources/views/layouts/master.blade.php index b3b5e5c27e96a357b66703d3eb4b5bc99ed9b525..e3fb12d53d7a8c89d3fba904c6525b3af815578b 100644 --- a/app/Modules/Bbs/Resources/views/layouts/master.blade.php +++ b/app/Modules/Bbs/Resources/views/layouts/master.blade.php @@ -8,8 +8,8 @@