美文网首页
解决Laravel deleted is null 问题

解决Laravel deleted is null 问题

作者: 可望不可j | 来源:发表于2022-02-10 17:31 被阅读0次

    1、涉及到的文件

    vendor/laravel/framework/src/Illuminate/Database/Eloquent/SoftDeletes.php
    vendor/laravel/framework/src/Illuminate/Database/Eloquent/SoftDeletingScope.php

    2、涉及点

    原字段 deleted_at 保留,新增 deleted_status
    软删时,将 deleted_status 状态改为 1
    查询时,将 deleted_status = 1 注入到全局
    恢复数据时,将 deleted_status 改为 0deleted_at 改为 null

    3、修改步骤如下:

    SoftDeletes.phpSoftDeletingScope.php 文件复制到 app/Traits 目录下
    开始修改 SoftDeletes.php 文件

    <?php
    
    namespace App\Traits;
    use Illuminate\Support\Facades\Log;
    
    /**
     * @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 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()
        {
            // 修改为 App\Models 命名空间下的 SoftDeletingScope
            static::addGlobalScope(new SoftDeletingScope);
        }
    
        /**
         * Initialize the soft deleting trait for an instance.
         *
         * @return void
         */
        public function initializeSoftDeletes()
        {
            $this->dates[] = $this->getDeletedAtColumn();
        }
    
        /**
         * Force a hard delete on a soft deleted model.
         *
         * @return bool|null
         */
        public function forceDelete()
        {
            $this->forceDeleting = true;
    
            return tap($this->delete(), function ($deleted) {
                $this->forceDeleting = false;
    
                if ($deleted) {
                    $this->fireModelEvent('forceDeleted', false);
                }
            });
        }
    
        /**
         * Perform the actual delete query on this model instance.
         *
         * @return mixed
         */
        protected function performDeleteOnModel()
        {
            if ($this->forceDeleting) {
                $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() => $this->fromDateTime($time)];
    
            $this->{$this->getDeletedAtColumn()} = $time;
            if ($this->timestamps && !is_null($this->getUpdatedAtColumn())) {
                $this->{$this->getUpdatedAtColumn()} = $time;
    
                $columns[$this->getUpdatedAtColumn()] = $this->fromDateTime($time);
    
                // 修改处,状态改为删除
                $columns['deleted_status'] = 1;
            }
    
            $query->update($columns);
    
            $this->syncOriginalAttributes(array_keys($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->getDeletedAtColumn()} = null;
    
            // 修改处,还原正常
            $this->deleted_status = 0;
    
            // 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 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 getDeletedAtColumn()
        {
            return defined('static::DELETED_AT') ? static::DELETED_AT : 'deleted_at';
        }
    
        public function getDeletedStatusColumn()
        {
            return 'deleted_status';
        }
    
        /**
         * Get the fully qualified "deleted at" column.
         *
         * @return string
         */
        public function getQualifiedDeletedAtColumn()
        {
            return $this->qualifyColumn($this->getDeletedAtColumn());
        }
    }
    
    

    修改SoftDeletingScope.php 文件

    <?php
    
    namespace App\Traits;
    
    use Illuminate\Database\Eloquent\Builder;
    use Illuminate\Database\Eloquent\Model;
    use Illuminate\Database\Eloquent\Scope;
    use Illuminate\Support\Facades\Log;
    class SoftDeletingScope implements Scope
    {
        /**
         * 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->whereNull($model->getQualifiedDeletedAtColumn());
        //}
        public function apply(Builder $builder, Model $model)
        {
    
            // 修改处,获取正常的数据
            $builder->where($model->qualifyColumn('deleted_status'), 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->getDeletedAtColumn($builder);
                return $builder->update([
                    $column => $builder->getModel()->freshTimestampString(),
                    $builder->getModel()->getDeletedStatusColumn() => 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() => null]);
                return $builder->update([$builder->getModel()->getDeletedStatusColumn() => 0,$builder->getModel()->getDeletedAtColumn() => null]);
            });
        }
    
        /**
         * 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)->whereNull(
                //    $model->getQualifiedDeletedAtColumn()
                //);
                // 修改处,只获取正常的数据
                $builder->withoutGlobalScope($this)->where($builder->qualifyColumn('deleted_status'), 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)->whereNotNull(
                //    $model->getQualifiedDeletedAtColumn()
                //);
                // 修改处,只获取已删除的数据
                $builder->withoutGlobalScope($this)->where($builder->qualifyColumn('deleted_status'), 1);
    
                return $builder;
            });
        }
    }
    
    

    4、使用

    在需要使用软删的模型增加字段 deleted_status,并引入use App\Traits\SoftDeletes

    相关文章

      网友评论

          本文标题:解决Laravel deleted is null 问题

          本文链接:https://www.haomeiwen.com/subject/lxxokrtx.html