初識事件監聽

Moonshadow2333發表於2022-03-04

前言

《L02 Laravel 教程 - Web 開發實戰進階 ( Laravel 8.x )》的3.7節——認證後的提示中就用到了事件監聽。

雖然laravel提供了一套成熟的註冊登入的功能。在註冊時,需要使用者郵件認證,但是當使用者點選認證郵件中的連結後,就註冊成功並跳轉到主頁。但是問題是沒有任何反饋,這樣的體驗很不好。郵件認證的邏輯在vendor/laravel/ui/auth-backend/VerifiesEmails.php中,理論上只要修改驗證成功後的邏輯就好了,但是課程中提到修改vendor/laravel/ui/auth-backend/VerifiesEmails.php檔案是不可取的。那該怎麼辦呢?就涉及到今天這篇部落格的主題了——事件監聽。通過對Verified事件進行監聽,就可以輕鬆的解決這個問題。

兩個例子:

教程中並沒有對事件監聽進行展開,文件寫的也很抽象,還是通過兩個例子來認識事件監聽吧:
1. 實現文章瀏覽的計數。
場景:使用者瀏覽文章後,瀏覽數+1。
具體實現:
1.1 註冊事件和監聽器
App\Providers\EventServiceProvider中註冊所有的事件監聽者。具體如下:

protected $listen = [
        'App\Events\BlogView' => [
            'App\Listeners\BlogViewListener',
        ],
    ];
// 鍵為事件,值為監聽器。

1.2 生成事件和監聽器

在命令列中執行php artisan event:generate,此命令將生成 EventServiceProvider 中列出的、尚不存在的任何事件或監聽器。

1.2.1 自動生成的事件檔案app/Events/BlogView.php如下:

<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class BlogView
{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('channel-name');
    }
}

1.2.2 自動生成的監聽器檔案app/Listeners/BlogViewListener.php如下:

<?php
namespace App\Listeners;
use App\Events\BlogView;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
class BlogViewListener
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }
    /**
     * Handle the event.
     *
     * @param  \App\Events\BlogView  $event
     * @return void
     */
    public function handle(BlogView $event)
    {
        //
    }
}

1.3 定義事件:考慮到要處理帖子模型,修改BlogView.php的構造器,在例項化的時候就將post例項賦值給post屬性。(對事件的處理視具體情況而定)

<?php
namespace App\Events;
use App\Models\Post;
...
class BlogView
{
    ...
    public $post;
    public function __construct(Post $post)
    {
        $this->post = $post;
    }
    ...
}

1.4 定義監聽器:事件發生時,瀏覽數+1。

<?php
namespace App\Listeners;
...
class BlogViewListener
{
    ...
    public function handle(BlogView $event)
    {
        $post = $event->post;
        dd('瀏覽數+1!');
    }
}

1.5 觸發事件:當使用者檢視文章的時候就觸發。


<?php

namespace App\Http\Controllers;
use App\Models\Post;
// 注意這裡需要引入BlogView類。
use App\Events\BlogView;
...
class PostController extends Controller
{
    ...
    public function show(){
        $post = Post::find(1);
        // 觸發事件
        event(new BlogView($post));
        return view('post.show');
    }
}

1.6 結果:

初識事件監聽

2. 物流發貨後,發簡訊通知使用者。

前輩的這篇部落格——記錄下學習筆記(Laravel 中的事件監聽)寫的已經很清楚了,就不再贅言。

什麼是事件?

在第一個例子中,事件是檢視文章。

在第一個例子中,事件是物流發貨。

感覺事件可以是任何動作。

什麼是監聽器?

不太好下定義,但是可以通過監聽器的功能來理解什麼是監聽器。當監聽器用於監聽事件,事件一旦觸發,就執行相應的邏輯。

具體步驟

1. 註冊事件和監聽器。

2. 生成事件和監聽器。

3. 定義事件和監聽器。

4. 觸發事件。

注意事項

1. 如果希望再某個類的某個動作中觸發事件,需要在該類中引入事件類。例如:在第一個例子中,是在PostController類的show動作中觸發了事件,所以需要在PostController類中引入BlogView事件類:

<?php
// 注意這裡需要引入BlogView類。
use App\Events\BlogView;
...

class PostController extends Controller
{
    ...
}

2. 一個事件可以由多個監聽器監聽。在第二個例子中,物流發貨後,我希望可以同時傳送簡訊和微信通知使用者,可以通過定義兩個監聽器實現:

protected $listen = [

  'App\Events\OrderEvent' => [

      'App\Listeners\sendModel',

      'App\Listeners\sendPhone',

  ]

];

感謝laravel-china社群

laravel框架很多功能都封裝好了,所以在學課程的3.7節時,就感覺事件監聽不難。但是我去看文件的時候,又看的迷迷糊糊的。不過幸好有很多前輩在這個社群寫過很多優秀的,關於事件監聽的部落格,所以我很容易就收集到了例子。在這些例子中才對事件監聽有一點感覺,才知道該怎麼用。

參考:

1. Laravel 中的事件監聽

2. 記錄下學習筆記(Laravel 中的事件監聽)

3. 文件

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章