laravel 修改软删为:0(正常)、1(删除) 的形式

Laravel框架
446
0
0
2022-08-11

涉及到的文件

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

涉及点

  1. 原字段 deleted_at 保留,新增 deleted_status
  2. 软删时,将 deleted_status 状态改为 1
  3. 查询时,将 deleted_status = 1 注入到全局
  4. 恢复数据时,将 deleted_status 改为 0,deleted_at 改为 null
  5. 参考文档:www.kancloud.cn/baidu/laravel5/294...

修改步骤如下:

  1. SoftDeletes.phpSoftDeletingScope 文件复制到 app/Models 目录下
  2. 开始修改 SoftDeletes.php 文件
<?php

namespace App\Models;

/**
 * @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';
    }

    /**
     * Get the fully qualified "deleted at" column.
     *
     * @return string
     */ 
    public function getQualifiedDeletedAtColumn()
    {
        return $this->qualifyColumn($this->getDeletedAtColumn());
    }
}
  1. 修改 SoftDeletingScope 文件
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;

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(),
                'deleted_status' => 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(['deleted_status' => 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)->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;
        });
    }
}
  1. 在需要使用软删的模型增加字段 deleted_status,并引入 use App\Models\SoftDeletes