溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Laravel中監(jiān)聽事件和觀察者模式的使用示例

發(fā)布時(shí)間:2021-01-13 09:21:42 來源:億速云 閱讀:393 作者:小新 欄目:編程語言

這篇文章將為大家詳細(xì)講解有關(guān)Laravel中監(jiān)聽事件和觀察者模式的使用示例,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

在理解了觀察者模式后,我們開始正文

Laravel 的事件提供了一個(gè)簡單的觀察者實(shí)現(xiàn),能夠訂閱和監(jiān)聽?wèi)?yīng)用中發(fā)生的各種事件。事件類保存在 app/Events 目錄中,而這些事件的的監(jiān)聽器則被保存在 app/Listeners 目錄下。這些目錄只有當(dāng)你使用 Artisan 命令來生成事件和監(jiān)聽器時(shí)才會被自動創(chuàng)建。

事件機(jī)制是一種很好的應(yīng)用解耦方式,因?yàn)橐粋€(gè)事件可以擁有多個(gè)互不依賴的監(jiān)聽器。例如,如果你希望每次訂單發(fā)貨時(shí)向用戶發(fā)送一個(gè) Slack 通知。你可以簡單地發(fā)起一個(gè) OrderShipped 事件,讓監(jiān)聽器接收之后轉(zhuǎn)化成一個(gè) Slack 通知,這樣你就可以不用把訂單的業(yè)務(wù)代碼跟 Slack 通知的代碼耦合在一起了。

手動生成一個(gè)事件

比如通過 artisan 命令手動生成一個(gè) UserLogin 事件:

php artisan make:event UserLogin

在 app/Events 中就會自動生成一個(gè) UserLogin.php 文件,內(nèi)容不多,如下:

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

定義監(jiān)聽器

一個(gè)事件可以被一個(gè)或多個(gè)監(jiān)聽器監(jiān)聽,也就是觀察者模式,我們可以定義多個(gè)監(jiān)聽器,當(dāng)這個(gè)事件發(fā)生,執(zhí)行一系列邏輯。

在 EventServiceProvider 的 $listen 中可以定義事件和監(jiān)聽器,如下:

protected $listen = [    'App\Events\UserLogin' => [        'App\Listeners\DoSomething1',
        'App\Listeners\Dosomething2',
    ],];

執(zhí)行 artisan 命令,就可以自動在 app/Lisenter 目錄生成監(jiān)聽器。

php artisan event:generate

這個(gè)命令也可以自動生成事件,如果沒有 UserLogin 這個(gè)事件會自動生成,而不需要手動生成。

可以看到 app/Listeners 目錄多了 DoSomething1.php 和 DoSomething2.php 兩個(gè)文件,我們看看其中一個(gè)內(nèi)容:

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

在兩個(gè)監(jiān)聽器的 handle 方法中我們打印一個(gè)日志來測試一下,如代碼 handle 方法所示。

分發(fā)和觸發(fā)事件

我們在某個(gè)控制器的方法中來分發(fā)事件,也就是觸發(fā)事件,看監(jiān)聽器是否正常工作。

就是一句話:

event(new UserLogin());

然后我們請求這個(gè)控制器,觀察日志,發(fā)現(xiàn)打印了日志:

[2018-06-17 10:04:29] local.INFO: do something1
[2018-06-17 10:04:29] local.INFO: do something2

那么這個(gè)事件-監(jiān)聽機(jī)制就正常工作了。

隊(duì)列異步處理

如果某個(gè)監(jiān)聽器需要執(zhí)行的操作比較慢,可以放到消息隊(duì)列進(jìn)行異步處理。

比如把上面的 DoSomething1 改成需要放入隊(duì)列的,只需要 implements ShoulQueue 接口。

class DoSomething1 implements ShouldQueue

也可以指定隊(duì)列驅(qū)動,如下代碼。

    /**
     * 任務(wù)應(yīng)該發(fā)送到的隊(duì)列的連接的名稱
     *
     * @var string|null     */
    public $connection = 'redis'; 
    /**
     * 任務(wù)應(yīng)該發(fā)送到的隊(duì)列的名稱
     *
     * @var string|null     */
    public $queue = 'listeners';

我們再次執(zhí)行控制器方法。

日志里沒有打印 do something1,只有 do something2,但是在 redis 隊(duì)列里發(fā)現(xiàn)了一個(gè)名為 queues:default 的列表。

{"job":"Illuminate\\Events\\CallQueuedHandler@call","data":{"class":"App\\Listeners\\DoSomething1","method":"handle","data":"a:1:{i:0;O:20:\"App\\Events\\UserLogin\":1:{s:6:\"socket\";N;}}"},"id":"3D7VDUwueYGtUvsazicWsifwWQxnnLID","attempts":1}

這個(gè)時(shí)候需要使用 php artisan queue:work 執(zhí)行隊(duì)列任務(wù),才是真正執(zhí)行 DoSomething1 這個(gè)監(jiān)聽器的 handle 方法。

關(guān)于“Laravel中監(jiān)聽事件和觀察者模式的使用示例”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識,如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI