」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 如何以及何時在 Laravel 實用程式碼範例中使用事件監聽器

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

發佈於2024-08-18
瀏覽:972

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

Laravel 的事件系统在处理 Web 应用程序中的复杂数据时非常出色,因为它是构建解耦且绝对复杂的应用程序的基石。本指南讲述了有关事件监听的实现和使用的极其详细的要点,尤其是在 2024 年,通过 Laravel 11 中最广泛的内容和详细的代码示例事件监听器提供了全新的视角。

*(A) 理解事件和监听器背后的核心
*

那么,让我们来分解一下,Laravel 中的事件确实代表了应用程序内的特定事件。侦听器是响应所有此类应用程序事件的类。这种模式不断促进关注点分离,并允许更多模块化和可测试的代码。

*(B) 创建事件
*

让我们首先创建一个复杂的事件,我们将使用 Artisan 命令来更好地解释我们强烈建议您也这样做

php artisan make:事件 OrderPlaced

此命令将在 app/Events 目录中生成一个新的事件类。让我们检查更详细的事件类

`命名空间 App\Events;

使用 App\Models\Order;
使用应用程序\模型\用户;
使用 Illuminate\Foundation\Events\Dispatchable;
使用 Illuminate\Queue\SerializesModels;
使用 Illuminate\Broadcasting\InteractsWithSockets;
使用 Illuminate\Broadcasting\PrivateChannel;
使用 Illuminate\Contracts\Broadcasting\ShouldBroadcast;

类 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 监听器,看看它如何进一步进展

`命名空间 App\Listeners;

使用 App\Events\OrderPlaced;
使用App\Mail\OrderConfirmation;
使用 Illuminate\Contracts\Queue\ShouldQueue;
使用 Illuminate\Queue\InteractsWithQueue;
使用 Illuminate\Support\Facades\Mail;
使用 Illuminate\Support\Facades\Log;

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 监听器

`命名空间 App\Listeners;

使用 App\Events\OrderPlaced;
使用 Illuminate\Contracts\Queue\ShouldQueue;
使用 Illuminate\Queue\InteractsWithQueue;
使用 Illuminate\Support\Facades\DB;
使用 Illuminate\Support\Facades\Log;

类 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 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

中注册这些事件和侦听器

`使用 App\Events\OrderPlaced;
使用 App\Listeners\SendOrderConfirmation;
使用 App\Listeners\UpdateInventory;

类 EventServiceProvider 扩展了 ServiceProvider
{
/**
* 应用程序的事件侦听器映射。
*
* @var 数组
*/
受保护的 $listen = [
订单放置::类 => [
SendOrderConfirmation::class,
更新库存::类,
],
];

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

    //
}

}`

调度事件:

我们可以从控制器或服务类调度事件

`使用 App\Events\OrderPlaced;
使用应用\模型\订单;
使用 Illuminate\Http\Request;
使用 Illuminate\Support\Facades\DB;

类 OrderController 扩展了 Controller
{
/**
* 下新订单。
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\JsonResponse
*/
公共函数 placeOrder(请求 $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]);
}

}`

在此示例中,我们将订单创建和事件分派包装在数据库事务中,以确保两者成功或根本不发生。

版本聲明 本文轉載於:https://dev.to/danish/how-when-to-use-event-listeners-in-laravel-11-practical-code-examples-29mn?1如有侵犯,請聯絡study_golang@163 .com刪除
最新教學 更多>
  • 如何將 HTML 附加到容器元素而不出現 InnerHTML 陷阱?
    如何將 HTML 附加到容器元素而不出現 InnerHTML 陷阱?
    在沒有innerHTML的情況下將HTML附加到容器元素重新訪問當前的問題是如何將HTML附加到容器元素,同時避免限制以及使用innerHTML屬性的陷阱。正如OP正確指出的那樣,innerHTML由於其替換現有內容的行為,可能會破壞嵌入媒體等動態元素。 幸運的是,有一個替代方案可以克服這些問題:i...
    程式設計 發佈於2024-11-06
  • 持續測試:確保 DevOps 管道的質量
    持續測試:確保 DevOps 管道的質量
    持续测试是现代软件开发中的关键实践,尤其是在 DevOps 框架内。它涉及在整个软件交付管道中自动执行测试,以确保对代码库所做的每项更改都得到彻底验证。通过将测试集成到开发过程的每个阶段,持续测试旨在尽早发现和解决缺陷,从而显着降低生产故障的风险。 什么是持续测试? 持续测试是作为软件交付管道的一...
    程式設計 發佈於2024-11-06
  • 背景顏色改變視頻
    背景顏色改變視頻
    在 Instagram 上關注我們 在本影片教學中,我將指導您使用 HTML、CSS 和 JavaScript 建立令人驚嘆的 Instagram 卡片。這張卡片具有充滿活力的變色邊框、圓形個人資料圖片和「關注我們」按鈕,為您的線上形象增添了吸引力。該專案非常適合增強您的作品集或社交媒體頁面,展示了...
    程式設計 發佈於2024-11-06
  • 如何使用 PHP 清除瀏覽器快取?
    如何使用 PHP 清除瀏覽器快取?
    使用 PHP 清除瀏覽器快取瀏覽器快取將經常存取的檔案儲存在本地,從而縮短網站載入時間。但是,如果快取的檔案已過時,它也會幹擾測試和開發。本文說明如何使用 PHP 清除瀏覽器快取。 清除瀏覽器快取的PHP 碼以下PHP 代碼將標頭髮送到客戶端瀏覽器,指示其清除其快取:header("Cac...
    程式設計 發佈於2024-11-06
  • AWS Lambda 與 Go,初始樣板
    AWS Lambda 與 Go,初始樣板
    照片由 Lukáš Vaňátko 在 Unsplash 上拍摄 介绍 Go 由于其简单性一直是我最喜欢的语言之一。最近,我决定弄清楚如何使用用 Go 编写的 lambda 函数创建一个简单的样板无服务器项目。我对工具和开发人员体验很好奇。 目标 我想创建一个 RES...
    程式設計 發佈於2024-11-06
  • 在 Laravel 中對底部為空值和非空值的行進行降序排序
    在 Laravel 中對底部為空值和非空值的行進行降序排序
    使用資料庫時,經常會遇到某些欄位可能為空或 NULL 的情況。經常出現的一個挑戰是如何對記錄進行排序,以便具有空字段的行出現在結果集的底部,而具有非空值的行以有意義的方式排序(例如,降序)。在這篇文章中,我將透過一個實際範例向您展示如何在 Laravel 中實現這一目標。 設想 假...
    程式設計 發佈於2024-11-06
  • 橄欖油的好處
    橄欖油的好處
    橄欖油的好處 橄欖油通常被譽為地中海飲食的基石,不僅可以為各種菜餚增添風味,而且還對健康有益。橄欖油從橄欖樹的果實中提取,已經使用了幾個世紀,現代研究不斷發現它的許多優點。以下是將橄欖油納入飲食的一些主要好處: 1. 心臟健康 橄欖油富含單元不飽和脂肪,尤其是油酸,...
    程式設計 發佈於2024-11-06
  • JSON Diff:開發人員完整指南
    JSON Diff:開發人員完整指南
    JSON(JavaScript 对象表示法)是一种广泛使用的数据格式,用于在系统之间交换信息。当开发人员使用 API、数据库和配置时,确保 JSON 数据保持一致和准确至关重要。这就是 JSON diff 发挥作用的地方。 JSON diff 工具允许开发人员快速发现两个 JSON 结构之间的差异...
    程式設計 發佈於2024-11-06
  • 你應該知道的 JavaScript 技巧
    你應該知道的 JavaScript 技巧
    蔡喬佈撰寫 1. 控制台.log 為控制台日誌新增顏色 別再這樣了! ❌ 試試這個吧。 ✅ 但如果你有一個物件數組,嘗試這個會更好嗎? 如果您想測量程式碼中某些操作的運行速度,請嘗試此操作。 執行console.time和console.timeEnd來測量瀏覽器控制台中花費的時...
    程式設計 發佈於2024-11-06
  • 掌握使用 Python 抓取 Google Scholar 的藝術
    掌握使用 Python 抓取 Google Scholar 的藝術
    如果您正在深入进行学术研究或数据分析,您可能会发现自己需要来自 Google 学术搜索的数据。不幸的是,没有官方的 Google Scholar API Python 支持,这使得提取这些数据有点棘手。然而,凭借正确的工具和知识,您可以有效地抓取 Google Scholar。在这篇文章中,我们将探...
    程式設計 發佈於2024-11-06
  • 使用 Go、Clean Architecture 和 PostgreSQL 建立強大的電子商務平台
    使用 Go、Clean Architecture 和 PostgreSQL 建立強大的電子商務平台
    概述 我們的目標是開發一個全面的電子商務解決方案,可以處理從產品管理到訂單處理的所有事務。該平台將成為線上業務的堅實基礎,能夠擴展以滿足不斷增長的需求並適應不斷變化的市場需求。 我們的電子商務平台的主要功能包括: 使用者驗證與個人資料管理 包含類別和子類別的產品目錄 購物車功能 ...
    程式設計 發佈於2024-11-06
  • Redis 解釋:主要功能、用例和實踐項目
    Redis 解釋:主要功能、用例和實踐項目
    Introduction Redis is an open-source, in-memory data structure store used as a database, cache, and message broker. It’s known for its perfor...
    程式設計 發佈於2024-11-06
  • 如何在 macOS 上設定 MySQL 自動啟動:開發人員逐步指南
    如何在 macOS 上設定 MySQL 自動啟動:開發人員逐步指南
    作為開發人員,我們經常發現自己在本地電腦上使用 MySQL 資料庫。雖然每次系統啟動時手動啟動 MySQL 是可以管理的,但這可能是一項乏味的任務。在本指南中,我們將逐步介紹將 MySQL 設定為在 macOS 上自動啟動的流程,從而節省您的時間並簡化您的工作流程。 先決條件 在我...
    程式設計 發佈於2024-11-06
  • 掌握 TypeScript:了解擴充的力量
    掌握 TypeScript:了解擴充的力量
    TypeScript 中的 extends 关键字就像一把瑞士军刀。它用于多种上下文,包括继承、泛型和条件类型。了解如何有效地使用扩展可以生成更健壮、可重用和类型安全的代码。 使用扩展进行继承 extends 的主要用途之一是继承,允许您创建基于现有接口或类的新接口或类。 inter...
    程式設計 發佈於2024-11-06
  • 如何將具有群組計數的欄位新增至 Pandas 中的分組資料框?
    如何將具有群組計數的欄位新增至 Pandas 中的分組資料框?
    如何在Pandas中向分組資料框中添加列在資料分析中,經常需要將資料分組並進行計算每組。 Pandas 透過其 groupby 函數提供了一種便捷的方法來做到這一點。一個常見的任務是計算每個組中某一列的值,並將包含這些計數的列加入到資料幀中。 考慮資料幀df:df = pd.DataFrame({'...
    程式設計 發佈於2024-11-06

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3