定制 merkeleon/laravel-transactional-events 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

merkeleon/laravel-transactional-events

Composer 安装命令:

composer require merkeleon/laravel-transactional-events

包简介

Transactional layer for Laravel Event Dispatcher

README 文档

README

This package introduces a transactional layer to the Laravel Event Dispatcher. Its purpose is to ensure, without changing a single line of code, consistency between events dispatched and database transactions. This behavior is also applicable to Eloquent events, such as saved and created.

Introduction

Let's start with a simple example of ordering tickets. Assume that it involves database changes and a payment registration and that the custom event OrderWasProcessed is dispatched immediately after the order is processed in the database.

DB::transaction(function() {
    $user = User::find(...);
    $concert = Concert::find(...);
    $order = $concert->orderTickets($user, 3);
    event(new OrderWasProcessed($order));
    PaymentService::registerOrder($order);
});

The transaction in the above example may fail for several reasons: an exception may occur in the orderTickets method or in the payment service or simply due to a deadlock.

A failure will rollback the database changes made during the transaction. However, this is not true for the OrderWasProcessed event, which is actually dispatched and eventually executed. Considering that this event may result in sending an e-mail with the order confirmation, managing it the right way becomes mandatory.

The purpose of this package is to actually dispatch events if and only if the transaction in which they were dispatched commits. For instance, in the above example the OrderWasProcessed event would not be dispatched if the transaction fails.

Please note that events dispatched out of transactions will bypass the transactional layer, meaning that they will be handled by the default Event Dispatcher. This is true also for events in which the $halt parameter is set to true.

Installation

Laravel Package
5.8.x 1.0.x

Laravel

The installation of this package in Laravel is automatic thanks to the Package Auto-Discovery feature of Laravel 5.5+. Just add this package to the composer.json file and it will be ready for your application.

composer require merkeleon/laravel-transactional-events

A configuration file is also available for this package. Run the following command to copy the provided configuration file transactional-events.php your config folder.

php artisan vendor:publish --provider="Merkeleon\Events\EventServiceProvider"

Lumen

As Lumen is built on top of Laravel packages, this package should also work smoothly on this micro-web framework. Run the following command to install this package:

composer require merkeleon/laravel-transactional-events

In order to configure the behavior of this package, copy the configuration files:

cp vendor/merkeleon/laravel-transactional-events/src/config/transactional-events.php config/transactional-events.php

Then, in bootstrap/app.php, register the configuration and the service provider:
Note: This package must be registered after the default EventServiceProvider, so your event listeners are not overriden.

// The default EventServiceProvider must be registered.
$app->register(App\Providers\EventServiceProvider::class);

...

$app->configure('transactional-events');
$app->register(Merkeleon\Events\EventServiceProvider::class);

Usage

The transactional layer is enabled by default for the events placed under the App\Events namespace.

However, the easiest way to make your events behave as transactional events is by implementing the contract Merkeleon\Events\Contracts\TransactionalEvent.
Note that events that implement it will behave as transactional events even when excluded in config.

namespace App\Events;

use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
...
use Merkeleon\Events\Contracts\TransactionalEvent;

class TicketsOrdered implements TransactionalEvent
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    ...
}

As this package does not require any changes in your code, you are still able to use the Event facade and call the event() or broadcast() helper to dispatch an event:

Event::dispatch(new App\Event\TicketsOrdered) // Using Event facade
event(new App\Event\TicketsOrdered) // Using event() helper method
broadcast(new App\Event\TicketsOrdered) // Using broadcast() helper method

Even if you are using queues, they will still work smothly because this package does not change the core behavior of the event dispatcher. They will be enqueued as soon as the active transaction succeeds. Otherwise, they will be discarded.

Reminder: Events are considered transactional when they are dispatched within transactions. When an event is dispatched out of transactions, it bypasses the transactional layer.

Configuration

The following keys are present in the configuration file:

Enable or disable the transactional behavior by changing the following property:

'enable' => true

By default, the transactional behavior will be applied to events on App\Events namespace. Feel free to use patterns and namespaces.

'transactional' => ['App\Events']

Choose the events that should always bypass the transactional layer, i.e., should be handled by the default event dispatcher. By default, all *ed Eloquent events are excluded.

'excluded' => [
    // 'eloquent.*',
    'eloquent.booted',
    'eloquent.retrieved',
    'eloquent.saved',
    'eloquent.updated',
    'eloquent.created',
    'eloquent.deleted',
    'eloquent.restored',
],

Known issues

Transactional events are not dispatched in tests.

This issue is fixed for Laravel 5.6.16+ (see #23832).
For previous versions, it is associated with the RefreshDatabase trait, namely when it uses database transactions to reset database after each test. This package relies on events dispached when transactions begin/commit/rollback and as each is executed within a transaction that rollbacks when test finishes, the dispatched application events are never actually dispatched. In order to get the expected behavior, use the Merkeleon\Testing\RefreshDatabase trait in your tests instead of the one originally provided by Laravel.

License

This package is open-sourced software licensed under the MIT license.

merkeleon/laravel-transactional-events 适用场景与选型建议

merkeleon/laravel-transactional-events 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 13.7k 次下载、GitHub Stars 达 1, 最近一次更新时间为 2019 年 04 月 02 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 merkeleon/laravel-transactional-events 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 merkeleon/laravel-transactional-events 我们能提供哪些服务?
定制开发 / 二次开发

基于 merkeleon/laravel-transactional-events 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 13.7k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 4
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 1
  • Watchers: 2
  • Forks: 2
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2019-04-02