首頁  >  文章  >  後端開發  >  如何以及何時在 Laravel 實用程式碼範例中使用事件監聽器

如何以及何時在 Laravel 實用程式碼範例中使用事件監聽器

王林
王林原創
2024-08-16 07:03:02292瀏覽

How & When To Use Event Listeners in Laravel  Practical Code Examples

Laravel 的事件系統在處理 Web 應用程式中的複雜資料方面非常出色,因為它是建立解耦且絕對複雜的應用程式的基石。本指南講述了有關事件監聽的實現和利用的極其詳細的要點,尤其是在 2024 年,透過 Laravel 11 中最廣泛的內容和詳細的程式碼範例事件監聽器提供了全新的視角。

*(A) 理解事件和監聽器背後的核心
*

那麼,讓我們來分解一下,Laravel 中的事件確實代表了應用程式內的特定事件。偵聽器是回應所有此類應用程式事件的類別。這種模式不斷促進關注點分離,並允許更多模組化和可測試的程式碼。

*(B) 建立活動
*

讓我們先創建一個複雜的事件,我們將使用 Artisan 命令來更好地解釋我們強烈建議您也這樣做

php artisan make:event OrderPlaced

此指令將在 app/Events 目錄中產生一個新的事件類別。讓我們來看看更詳細的事件類別

`命名空間 AppEvents;

使用AppModelsOrder;
使用 AppModelsUser;
使用 IlluminateFoundationEventsDispatchable;
使用 IlluminateQueueSerializesModels;
使用 IlluminateBroadcastingInteractsWithSockets;
使用 IlluminateBroadcastingPrivateChannel;
使用 IlluminateContractsBroadcastingShouldBroadcast;

類別 OrderPlaced 實作 ShouldBroadcast
{
使用 Dispatchable、InteractsWithSockets、SerializesModels;

public $order;
public $user;

/**
 * Create a new event instance.
 *
 * @param  \App\Models\Order  $order
 * @param  \App\Models\User  $user
 * @return void
 */
public function __construct(Order $order, User $user)
{
    $this->order = $order;
    $this->user = $user;
}

/**
 * Get the channels the event should broadcast on.
 *
 * @return \Illuminate\Broadcasting\Channel|array
 */
public function broadcastOn()
{
    return new PrivateChannel('orders.'.$this->user->id);
}

/**
 * The event's broadcast name.
 *
 * @return string
 */
public function broadcastAs()
{
    return 'order.placed';
}

}`

在這個擴充範例中,我們同時包含了 Order 和 User 模型。 SerializesModels 特徵一直確保當事件傳遞給排隊的偵聽器時,我們的 Eloquent 模型能夠正確序列化和反序列化。我們還實作了 ShouldBroadcast 接口,並定義了 broadcastOnbroadcastAs 方法,允許將此事件廣播到 websockets 進行即時更新。

*建立多個監聽器
*

對於單一事件,我們可能需要多個偵聽器。讓我們為 OrderPlaced 事件建立兩個偵聽器以進一步擴展範例。我只是希望你們能確保掌握一切的要點。因此,請參閱下面的程式碼範例

php artisan make:listener SendOrderConfirmation --event=OrderPlaced
php artisan make:listener UpdateInventory --event=OrderPlaced

現在你應該明白這個命令列會在我們的 app/Listeners 目錄中提供我們幾個新的監聽器類別。現在的問題是,在下面,我們將檢查 SendOrderConfirmation 偵聽器,看看它如何進一步進行

`命名空間 AppListeners;

使用AppEventsOrderPlaced;
使用AppMailOrderConfirmation;
使用 IlluminateContractsQueueShouldQueue;
使用 IlluminateQueueInteractsWithQueue;
使用 IlluminateSupportFacadesMail;
使用 IlluminateSupportFacadesLog;

SendOrderConfirmation 類別實作 ShouldQueue
{
使用 InteractsWithQueue;

/**
 * The number of times the job may be attempted.
 *
 * @var int
 */
public $tries = 3;

/**
 * Handle the event.
 *
 * @param  \App\Events\OrderPlaced  $event
 * @return void
 */
public function handle(OrderPlaced $event)
{
    $order = $event->order;
    $user = $event->user;

    try {
        Mail::to($user->email)->send(new OrderConfirmation($order));
        Log::info('Order confirmation email sent', ['order_id' => $order->id, 'user_id' => $user->id]);
    } catch (\Exception $e) {
        Log::error('Failed to send order confirmation email', ['order_id' => $order->id, 'user_id' => $user->id, 'error' => $e->getMessage()]);
        $this->fail($e);
    }
}

/**
 * Handle a job failure.
 *
 * @param  \App\Events\OrderPlaced  $event
 * @param  \Throwable  $exception
 * @return void
 */
public function failed(OrderPlaced $event, $exception)
{
    Log::error('Order confirmation listener failed', ['order_id' => $event->order->id, 'user_id' => $event->user->id, 'error' => $exception->getMessage()]);
}

}`

這個監聽器已經實現了ShouldQueue接口,表明它應該排隊。我們新增了錯誤處理、日誌記錄,並定義了失敗方法來處理失敗。 $tries 屬性將設定為允許在失敗時進行多次嘗試。
現在,讓我們來看看 UpdateInventory 監聽器

`命名空間 AppListeners;

使用AppEventsOrderPlaced;
使用 IlluminateContractsQueueShouldQueue;
使用 IlluminateQueueInteractsWithQueue;
使用 IlluminateSupportFacadesDB;
使用 IlluminateSupportFacadesLog;

類別 UpdateInventory 實作 ShouldQueue
{
使用 InteractsWithQueue;

/**
 * Handle the event.
 *
 * @param  \App\Events\OrderPlaced  $event
 * @return void
 */
public function handle(OrderPlaced $event)
{
    $order = $event->order;

    DB::transaction(function () use ($order) {
        foreach ($order->items as $item) {
            $product = $item->product;

            if ($product->stock < $item->quantity) {
                throw new \Exception("Insufficient stock for product: {$product->id}");
            }

            $product->decrement('stock', $item->quantity);
            Log::info("Inventory updated", ['product_id' => $product->id, 'quantity' => $item->quantity]);
        }
    });
}

/**
 * Handle a job failure.
 *
 * @param  \App\Events\OrderPlaced  $event
 * @param  \Throwable  $exception
 * @return void
 */
public function failed(OrderPlaced $event, $exception)
{
    Log::error('Failed to update inventory', ['order_id' => $event->order->id, 'error' => $exception->getMessage()]);
}

}`

現在,您應該明白了,這個偵聽器的存在是出於一些原因,例如根據訂單商品升級庫存等。我們將庫存更新包裝在資料庫事務中以確保資料一致性。我們還添加了錯誤檢查以防止負庫存,並包括成功更新和失敗的日誌記錄。

*註冊事件與聽眾
*

我們將在 EventServiceProvider

中註冊這些事件和偵聽器

`使用 AppEventsOrderPlaced;
使用 AppListenersSendOrderConfirmation;
使用 AppListenersUpdateInventory;

class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
OrderPlaced::class => [
SendOrderConfirmation::class,
UpdateInventory::class,
],
];

/**
 * Register any events for your application.
 *
 * @return void
 */
public function boot()
{
    parent::boot();

    //
}

}`

Dispatching Events:

We can dispatch the event from a controller or service class

`use App\Events\OrderPlaced;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class OrderController extends Controller
{
/**
* Place a new order.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function placeOrder(Request $request)
{
$user = auth()->user();

    DB::transaction(function () use ($request, $user) {
        $order = Order::create($request->all());
        $order->user()->associate($user);
        $order->save();

        event(new OrderPlaced($order, $user));
    });

    return response()->json(['message' => 'Order placed successfully', 'order_id' => $order->id]);
}

}`

In this example, we have wrapped the order creation and event dispatching in a database transaction to ensure that both occur successfully or not at all.

以上是如何以及何時在 Laravel 實用程式碼範例中使用事件監聽器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn