DB::transaction() 可以将 Eloquent 查询作为事务执行吗?

Posted

技术标签:

【中文标题】DB::transaction() 可以将 Eloquent 查询作为事务执行吗?【英文标题】:Can DB::transaction() execute Eloquent queries as transaction? 【发布时间】:2018-04-23 18:47:15 【问题描述】:

我:这是一个混合问题 | 访客:(wtf?)这是什么意思?

我在一个问题中提出 2 个问题(因为它是紧密耦合的)

使用:Laravel 5.5 & mysql

1。 eloquent中如何删除相关模型?

我正在尝试删除具有以下关系的User

属于Address, 属于Package, hasManyOrders, hasManyComments

OrdersUserProduct 被删除时级联 当UserPost 被删除时COmments 级联。

现在如何删除User 并自动删除关联的orderscomments

当我尝试使用 $user->delete() 删除时,laravel 抛出异常:

SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`cybertron`.`comments`, CONSTRAINT `comments_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)) (SQL: delete from `users` where `id` = 4)

所以我决定使用一个事务来删除、User、关联的订单和 cmets, 确保所有内容都被删除。

但我没有在 eloquent 中找到任何事务,而是在查询构建器 (DB) 中。

2。如果我使用数据库中的事务并使用 eloquent 删除用户 ($user->delete),这会被视为事务吗?

喜欢:

DB::transaction(function() 

      $user->comments->delete();
      $user->orders->delete();
      $user->delete();
);

如果没有,我怎么能与 Eloquent 进行交易?

任何帮助将不胜感激

【问题讨论】:

【参考方案1】:

    您有 Eloquent events 用于删除,但您也可以像这样覆盖默认删除方法:

    public function delete()
    
        \DB::transaction(function() 
            $this->comments()->delete();
            $this->orders()->delete();
            parent::delete(); 
         );
    
    

    是的,Eloquent 本身没有事务。您可以使用显示的事务并将 Eloquent 或查询构建器包装在其中。请注意,在您的情况下,您应该使用 comments()orders() 而不是 commentsorders

【讨论】:

感谢您的回答,经过一个小时的搜索和测试,我实际上是在那天晚上弄明白的。您的回答绝对是这种情况下的解决方案。 在这种情况下应该使用comments() 而不是comments,因为我们处理的不是集合而是模型,对吗? 是的,这是因为我们使用的是关系,如果要删除关系项()应该添加【参考方案2】:

@Marcin

如果您在模型上使用事件,为了级联删除,您需要确保您了解在查询对象上运行删除与在模型对象上运行删除之间的区别

例如: $this->orders()->delete(); - 此行实际上并未加载订单模型 - $this->orders() - 返回一个查询对象 - 这行实际上会运行一个 DELETE SQL 语句

为了在删除用户时按顺序启动删除事件,您必须执行一次 foreach foreach($user->orders as $order) $order->delete();

当user::deleting事件启动时,加载用户的所有订单并调用delete; 这将触发 order::deleting 事件,我们将加载所有评论对象并删除它们

【讨论】:

感谢您的详细解释。这会有所帮助。

以上是关于DB::transaction() 可以将 Eloquent 查询作为事务执行吗?的主要内容,如果未能解决你的问题,请参考以下文章

laravel transaction : laravel 的事务是不支持eloquent的, 要用DB::的方式

Laravel DB::transaction 不回滚异常

错误:未定义不是 ReactNative 中的对象(评估“db.transaction”)

PHP Elo评级系统测试

Elo rating system 模拟

为啥 Dexie 在 transaction() 中 modify() 后返回旧数据?