【问题标题】:Laravel DB transaction and eventsLaravel DB 事务和事件
【发布时间】:2021-05-14 03:54:29
【问题描述】:

我希望如果任何产品更新,我们会在交易完成后触发一次事件

DB::transaction(function() {
   foreach($products as $product) {
       $product = Product::find($product->id) ;
       $product->price = 2;
       $product->update();
   } 
});

【问题讨论】:

  • 可以在更新产品前使用isDirty方法检查产品是否有属性变化laravel.com/docs/8.x/eloquent#examining-attribute-changes
  • 您可以在$product->update() 行下触发事件。有什么大不了的?
  • @AbdullahShakir 您提到的唯一处理方法是在提交事务之前触发事件,这在某些情况下可能会导致有趣的场景:如果事务由于某些原因而失败怎么办错误或事件将针对尚未保存在数据库中的对象进行处理
  • 我明白了。 @PrideMutumbami 想在事务提交后触发事件?

标签: database laravel eloquent


【解决方案1】:

Laravel Eloquent 模型让你沉浸在以下时刻

retrievedcreatingcreatedupdatingupdatedsavingsaveddeletingdeletedrestoredrestored、@9876543332 @

以上事件因 laravel 版本而异。

Laravel 8.x

如果您使用的是 Laravel 8.x,那么 Laravel 会通过事务处理 eloquent 事件。

你只需要在你的观察者中使用public $afterCommit = true;。 然后 eloquent 事件将在提交事务后触发。

参考:https://laravel.com/docs/8.x/eloquent#observers-and-database-transactions

Laravel

使用以下版本的朋友,请看下面的代码。

您需要在app/Traits 文件夹中创建一个特征

app/Traits/TransactionalEloquentEvents.php

<?php

namespace App\Traits;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Events\TransactionCommitted;
use Illuminate\Support\Facades\Log;

    trait TransactionalEloquentEvents
    {
        protected static $eloquentEvents = ['created', 'updated'];
    
        protected static $queuedTransactionalEvents = [];
    
        public static function bootTransactionalEloquentEvents()
        {
            $dispatcher = static::getEventDispatcher();
            if (!$dispatcher) {
                return;
            }
    
            foreach (self::$eloquentEvents as $event) {
                static::registerModelEvent($event, function (Model $model) use ($event) {
                    /*get updated parameters*/
                    $updatedParams = array_diff($model->getOriginal(),$model->getAttributes());
                    if ($model->getConnection()->transactionLevel()) {
                        self::$queuedTransactionalEvents[$event][] = $model;
                    } else {
                        Log::info('Event fired without transaction '.$event. json_encode($updatedParams));
                        /* Do your operation here*/
                    }
                });
            }
    
            $dispatcher->listen(TransactionCommitted::class, function (TransactionCommitted $event) {
                if ($event->connection->transactionLevel() > 0) {
                    return;
                }
                foreach ((self::$queuedTransactionalEvents ?? []) as $eventName => $models) {
                    foreach ($models as $model) {
                        Log::info('Event fired with transaction '.$eventName);
                        /* Do your operation here*/
                    }
                }
                self::$queuedTransactionalEvents = [];
            });
        }
    }

在你的模型中app/Models/Product.php

<?php

namespace App\Models;

use App\Traits\TransactionalEloquentEvents;

class Product extends Model
{
    use TransactionalEloquentEvents;

}

注意:在updated eloquent 事件的情况下。您将通过$updatedParams 变量获取更新后的参数。

上述案例处理事务和非事务模型操作。

我在这里为每个活动维护一个日志。你也可以做你的手术。

【讨论】:

  • public $afterCommit = true; 是否也将-ing 事件延迟到事务之后?我没有看到任何迹象表明$afterCommit 仅处理-ed 事件,但我无法完全理解在事务提交后触发的-ing 事件。
  • -ing 事件是 pre-hook,-ed 是 post-hook
  • 是的,但是如果 $afterCommit 标志在观察者中为真,在数据库事务期间是否会触发 -ing 事件?否则,在触发 -ing 事件之前,该记录将实际存在于数据库中(事务之后)。
  • 在数据库事务中创建模型时,您可能希望指示观察者仅在提交数据库事务后执行其事件处理程序。您可以通过在观察者上定义 $afterCommit 属性来完成此操作。如果数据库事务不在进行中,事件处理程序将立即执行:
  • 简而言之,但是在 TransactionCommitted 事件之后
【解决方案2】:

我刚刚检查了 Laravel 源代码。我认为您可以利用开箱即用的Illuminate\Database\Events\TransactionCommitted 事件。您可以简单地使用EventServiceProvider 中的侦听器注册此事件:

namespace App\Providers;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        TransactionCommitted::class => [
            WhatYouWantToDo::class,
        ],
    ];
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-29
    • 2013-01-29
    • 2012-06-28
    • 2021-07-20
    • 1970-01-01
    • 2018-05-11
    • 2015-01-10
    • 1970-01-01
    相关资源
    最近更新 更多