当模型被软删除时,它们并不会真的从数据库中被移除。而是会在模型上设置一个 deleted_at 属性并将其添加到数据库。如果对应模型被软删除,则deleted_at字段的值为删除时间,否则该值为空。
1.做一些设置
首先在模型类中要使用SoftDeletestrait,该trait为软删除提供一系列相关方法,具体可参考源码Illuminate\Database\Eloquent\SoftDeletes,此外还要设置$date属性数组,将deleted_at置于其中:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; //这句必须要
class Post extends Model {
use SoftDeletes; //这句必须要
//...其他一些设置
protected $dates = ['delete_at'];
}
2.向数据库中的相应数据表添加delete_at字段
1>这里我们使用数据迁移来实现
php artisan make:migration alter_posts_deleted_at --table=posts
2>此时在database/migrations文件夹下会生成一个相应文件,更改如下
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AlterPostsDeletedAt extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
Schema::table('posts', function (Blueprint $table) {
$table->softDeletes();
});
}
...//其它方法
}
3>再次运行命令 php artisan migrate ,发现数据库相应的数据表中已经有delete_at字段了
3.使用方法
在模型上调用 delete 方法时,deleted_at 字段将会被设置成目前的日期和时间。而且,当查找有启用软删除的模型时,被软删除的模型将会自动从所有查找结果中排除。
//在模型上调用delete方法
$post = Post::find(6); $post->delete();
//要确认指定的模型实例是否已经被软删除,可以使用 trashed 方法:
if($post->trashed()){
echo '软删除成功!';
dd($post);
}else{
echo '软删除失败!';
}
//查找被软删除的模型
$flights = App\Flight::withTrashed() ->where('account_id', 1) ->get();
//onlyTrashed 方法会只获取已被软删除的模型:
$flights = App\Flight::onlyTrashed() ->where('airline_id', 1) ->get();
//恢复单个已经被软删除的模型
$flight = Flight::withTrashed()-find(1); //这里要注意如果被软删除直接find是查不到的
$flight->restore();
//恢复多个模型
App\Flight::withTrashed() ->where('airline_id', 1) ->restore();
// 强制删除单个模型实例...
$flight->forceDelete();
// 强制删除所有相关模型...
$flight->history()->forceDelete();
在实际项目中,对数据频繁使用删除操作会导致性能问题,软删除的作用就是把数据加上删除标记,而不是真正的删除,同时也便于需要的时候进行数据的恢复。
要使用软删除功能,需要引入SoftDelete trait,例如User模型按照下面的定义就可以使用软删除功能:
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time';
}
deleteTime属性用于定义你的软删除标记字段,ThinkPHP的软删除功能使用时间戳类型(数据表默认值为Null),用于记录数据的删除时间。
可以支持defaultSoftDelete属性来定义软删除字段的默认值,在此之前的版本,软删除字段的默认值必须为null。
<?php
namespace app\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model
{
use SoftDelete;
protected $deleteTime = 'delete_time';
protected $defaultSoftDelete = 0;
}
可以用类型转换指定软删除字段的类型,建议数据表的所有时间字段统一一种类型。
定义好模型后,我们就可以使用:
// 软删除
User::destroy(1);
// 真实删除
User::destroy(1,true);
$user = User::find(1);
// 软删除
$user->delete();
// 真实删除
$user->delete(true);
默认情况下查询的数据不包含软删除数据,如果需要包含软删除的数据,可以使用下面的方式查询:
User::withTrashed()->find();
User::withTrashed()->select();
如果仅仅需要查询软删除的数据,可以使用:
User::onlyTrashed()->find();
User::onlyTrashed()->select();
恢复被软删除的数据
$user = User::onlyTrashed()->find(1);
$user->restore();
软删除的删除操作仅对模型的删除方法有效,如果直接使用数据库的删除方法则无效,例如下面的方式无效(将不会执行任何操作)。
$user = new User;
$user->where('id',1)->delete();
grid中加回收站
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; //这句必须要
class Post extends Model {
use SoftDeletes; //这句必须要
//...其他一些设置
protected $dates = ['delete_at'];
}
protected function units_grid()
{
$grid->actions(function ($actions){
$actions->disableDelete();
$actions->disableEdit();
$actions->disableView();
$back_url = $_SERVER["QUERY_STRING"];
if (\request('_scope_') == 'trashed') {
$actions->append('<a class="btn btn-sm btn-default grid-row-restore" data-id="'.$actions->getKey().'">恢复</a>');
}else{
$actions->append('<a class="btn btn-sm btn-default grid-row-delete" data-id="'.$actions->getKey().'">删除</a>');
}
});
$grid->filter(function (Grid\Filter $filter){
$filter->scope('trashed', '回收站')->onlyTrashed();
$filter->disableIdFilter();
.....
});
return $grid;
}