Eloquent ORM 实例教程 —— 模型删除及软删除相关实现


guide-to-eloquent-orm

1、删除模型

1.1 使用delete删除模型

删除模型很简单,先获取要删除的模型实例,然后调用delete方法即可:

  1. $post = Post::find(5);
  2. if($post->delete()){
  3. echo '删除文章成功!';
  4. }else{
  5. echo '删除文章失败!';
  6. }

该方法返回truefalse

1.2 使用destroy删除模型

当然如果已知要删除的模型id的话,可以用更简单的方法destroy直接删除:

  1. $deleted = Post::destroy(5);

你也可以一次传入多个模型id删除多个模型:

  1. $deleted = Post::destroy([1,2,3,4,5]);

调用destroy方法返回被删除的记录数。

1.3 使用查询构建器删除模型

既然前面提到Eloquent模型本身就是查询构建器,也可以使用查询构建器风格删除模型,比如我们要删除所有浏览数为0的文章,可以使用如下方式:

  1. $deleted = Models\Post::where('views', 0)->delete();

返回结果为被删除的文章数。

2、软删除及其相关实现

2.1 软删除实现

上述删除方法都会将数据表记录从数据库删除,此外Eloquent模型还支持软删除。

所谓软删除指的是数据表记录并未真的从数据库删除,而是将表记录的标识状态标记为软删除,这样在查询的时候就可以加以过滤,让对应表记录看上去是被”删除“了。Laravel中使用了一个日期字段作为标识状态,这个日期字段可以自定义,这里我们使用deleted_at,如果对应模型被软删除,则deleted_at字段的值为删除时间,否则该值为空。

要让Eloquent模型支持软删除,还要做一些设置。首先在模型类中要使用SoftDeletestrait,该trait为软删除提供一系列相关方法,具体可参考源码Illuminate\Database\Eloquent\SoftDeletes,此外还要设置$date属性数组,将deleted_at置于其中:

  1. <?php
  2.  
  3. namespace App\Models;
  4.  
  5. use Illuminate\Database\Eloquent\Model;
  6. use Illuminate\Database\Eloquent\SoftDeletes;
  7.  
  8. class Post extends Model
  9. {
  10. use SoftDeletes;
  11.  
  12. //设置表名
  13. public $table = 'posts';
  14.  
  15. //设置主键
  16. public $primaryKey = 'id';
  17.  
  18. //设置日期时间格式
  19. public $dateFormat = 'U';
  20.  
  21. protected $guarded = ['id','views','user_id','updated_at','created_at'];
  22.  
  23. protected $dates = ['delete_at'];
  24. }

然后对应的数据库posts中添加deleted_at列,我们使用迁移来实现,先执行Artisan命令:

  1. php artisan make:migration alter_posts_deleted_at --table=posts

然后编辑生成的PHP文件如下:

  1. <?php
  2.  
  3. use Illuminate\Database\Schema\Blueprint;
  4. use Illuminate\Database\Migrations\Migration;
  5.  
  6. class AlterPostsDeletedAt extends Migration
  7. {
  8. /**
  9. * Run the migrations.
  10. *
  11. * @return void
  12. */
  13. public function up()
  14. {
  15. Schema::table('posts', function (Blueprint $table) {
  16. $table->softDeletes();
  17. });
  18. }
  19.  
  20. ...//其它方法
  21. }

然后运行:

  1. php artisan migrate

这样posts中就有了deleted_at列。接下来,我们在控制器中编写测试代码:

  1. $post = Post::find(6);
  2. $post->delete();
  3. if($post->trashed()){
  4. echo '软删除成功!';
  5. dd($post);
  6. }else{
  7. echo '软删除失败!';
  8. }

在浏览器中访问http://laravel.app:8000/test,页面输出如下:

软删除后模型不显示

当我们再次通过下面这段代码获取所有文章:

  1. $posts = Post::all();
  2. dd($posts);

已经看不到id为6的文章的身影了。

2.2 查询结果包含软删除模型

那如果想要在查询结果中包含软删除的记录呢?可以使用SoftDeletes trait上的withTrashed方法:

  1. $posts = Post::withTrashed()->get();
  2. dd($posts);

执行之后页面显示如下:

查询结果包含软删除模型

id为6的文章又出现在了查询结果中。有时候我们只想要查看被软删除的模型,这也有招,通过SoftDeletes上的onlyTrashed方法即可:

  1. $posts = Post::onlyTrashed()->get();
  2. dd($posts);

执行后页面显示结果如下:

查询结果只包含软删除模型

2.3 软删除恢复

有时候我们需要恢复被软删除的模型,可以使用SoftDeletes提供的restore方法:

恢复单个模型

  1. $post = Post::find(6);
  2. $post->restore();

恢复多个模型

  1. Post::withTrashed()->where('id','>',1)->restore();

恢复所有模型

  1. Post::withTrashed()->restore();

恢复关联查询模型

  1. $post = Post::find(6);
  2. $post->history()->restore();

2.4 强制删除

如果模型配置了软删除但我们确实要删除改模型对应数据库表记录,则可以使用SoftDeletes提供的forceDelete方法:

  1. $post = Post::find(6);
  2. $post->forceDelete();

查看数据表可以发现id=6的表记录已经被删除,不复存在:

使用强制删除后的结果集

该方法也支持关联模型强制删除,我们后面讲到关联关系的时候再具体说明。