鍍金池/ 教程/ PHP/ 事件
Laravel Cashier
Eloquent ORM
HTTP 響應(yīng)
發(fā)行說明
擴(kuò)展包開發(fā)
HTTP 控制器
事件
擴(kuò)展框架
Contracts
開發(fā)
配置
表單驗(yàn)證
錯(cuò)誤與日志
Hashing
貢獻(xiàn)指南
郵件
Session
遷移與數(shù)據(jù)填充
查詢構(gòu)造器
Redis
升級(jí)向?qū)?/span>
概覽
緩存
服務(wù)提供者
Envoy 任務(wù)執(zhí)行器
隊(duì)列
單元測(cè)試
服務(wù)容器
文件系統(tǒng) / 云存儲(chǔ)
認(rèn)證
請(qǐng)求的生命周期
加密
模板
視圖 (View)
Laravel Homestead
Laravel 安裝指南
介紹
Command Bus
分頁
輔助方法
應(yīng)用程序結(jié)構(gòu)
HTTP 路由
HTTP 請(qǐng)求
基本用法
本地化
HTTP 中間件
結(jié)構(gòu)生成器
Facades
Laravel Elixir

事件

基本用法

Laravel 的 event 功能提供一個(gè)簡(jiǎn)單的觀察者實(shí)現(xiàn),允許你在應(yīng)用程序里訂閱與監(jiān)聽事件。事件類通常被保存在 app/Events 目錄下,而它們的處理程序則被保存在 app/Handlers/Events 目錄下。

你可以使用 Artisan 命令行工具產(chǎn)生一個(gè)新的事件類:

    php artisan make:event PodcastWasPurchased

訂閱事件

Laravel 里的 EventServiceProvider 提供了一個(gè)方便的地方注冊(cè)所有的事件處理程序。listen 屬性包含一個(gè)所有的事件 (鍵) 和相對(duì)應(yīng)的處理程序 (值) 的 數(shù)組。當(dāng)然,你可以依應(yīng)用程序的需求添加任何數(shù)量的事件到這個(gè)數(shù)組。舉個(gè)例子,讓我們來加上 PodcastWasPurchased 事件:

    /**
     * 應(yīng)用程序的事件處理程序?qū)φ铡?     *
     * @var array
     */
    protected $listen = [
        'AppEventsPodcastWasPurchased' => [
            'AppHandlersEventsEmailPurchaseConfirmation',
        ],
    ];

使用 Artisan 命令行命令 handler:event,來產(chǎn)生一個(gè)事件的處理程序:

    php artisan handler:event EmailPurchaseConfirmation --event=PodcastWasPurchased

當(dāng)然,在每次你需要一個(gè)處理程序或是事件時(shí),手動(dòng)地執(zhí)行 make:eventhandler:event 命令很麻煩。作為替代,簡(jiǎn)單地添加處理程序跟事件到你的 EventServiceProvider 并使用 event:generate 命令。這個(gè)命令將會(huì)產(chǎn)生任何在你的 EventServiceProvider 列出的事件跟處理程序:

    php artisan event:generate

觸發(fā)事件

現(xiàn)在我們準(zhǔn)備好使用 Event facade 觸發(fā)我們的事件:

    $response = Event::fire(new PodcastWasPurchased($podcast));

fire 方法返回一個(gè)響應(yīng)的數(shù)組,讓你可以用來控制你的應(yīng)用程序接下來要有什么反應(yīng)。

你也可以使用 event 輔助方法來觸發(fā)事件:

    event(new PodcastWasPurchased($podcast));

監(jiān)聽器閉包

你甚至可以不需對(duì)事件建立對(duì)應(yīng)的處理類。舉個(gè)例子,在你的 EventServiceProviderboot 方法里,你可以做下面這件事:

    Event::listen('AppEventsPodcastWasPurchased', function($event)
    {
        // 處理事件...
    });

停止繼續(xù)傳遞事件

有時(shí)候你會(huì)希望停止繼續(xù)傳遞事件到其他監(jiān)聽器。你可以通過從處理程序返回 false 來做到這件事:

    Event::listen('AppEventsPodcastWasPurchased', function($event)
    {
        // 處理事件...

        return false;
    });

事件處理隊(duì)列

需要把事件處理程序放到 隊(duì)列 嗎?這不能變得再更簡(jiǎn)單了。當(dāng)你產(chǎn)生處理程序,簡(jiǎn)單地使用 \--queued 旗標(biāo):

    php artisan handler:event SendPurchaseConfirmation --event=PodcastWasPurchased --queued

這將會(huì)產(chǎn)生一個(gè)實(shí)現(xiàn)了 IlluminateContractsQueueShouldBeQueued 接口的處理程序類。這樣就可以了!現(xiàn)在當(dāng)這個(gè)處理程序因?yàn)槭录l(fā)生被調(diào)用,它將會(huì)被事件配送器自動(dòng)地排進(jìn)隊(duì)列。

當(dāng)處理程序被隊(duì)列執(zhí)行,如果沒有異常被丟出,在執(zhí)行后該隊(duì)列中的任務(wù)將會(huì)自動(dòng)被刪除。你也可以手動(dòng)取用隊(duì)列中的任務(wù)的 deleterelease 方法。隊(duì)列處理程序默認(rèn)會(huì)引入的 IlluminateQueueInteractsWithQueue trait,讓你可以取用這些方法:

    public function handle(PodcastWasPurchased $event)
    {
        if (true)
        {
            $this->release(30);
        }
    }

如果你想要把一個(gè)已存在的處理程序轉(zhuǎn)換成一個(gè)隊(duì)列的處理程序,簡(jiǎn)單地手動(dòng)添加 ShouldBeQueued 接口到類。

事件訂閱者

定義事件訂閱者

事件訂閱者是個(gè)可以從類自身里面訂閱多個(gè)事件的類。訂閱者應(yīng)該定義 subscribe 方法,事件配送器實(shí)體將會(huì)被傳遞到這個(gè)方法:

    class UserEventHandler {

        /**
         * 處理用戶登錄事件。
         */
        public function onUserLogin($event)
        {
            //
        }

        /**
         * 處理用戶注銷事件。
         */
        public function onUserLogout($event)
        {
            //
        }

        /**
         * 注冊(cè)監(jiān)聽器給訂閱者。
         *
         * @param  IlluminateEventsDispatcher  $events
         * @return array
         */
        public function subscribe($events)
        {
            $events->listen('AppEventsUserLoggedIn', 'UserEventHandler@onUserLogin');

            $events->listen('AppEventsUserLoggedOut', 'UserEventHandler@onUserLogout');
        }

    }

注冊(cè)事件訂閱者

當(dāng)定義了訂閱者后,可以使用 Event 類注冊(cè)。

    $subscriber = new UserEventHandler;

    Event::subscribe($subscriber);

你也可以使用 服務(wù)容器 自動(dòng)解析訂閱者。簡(jiǎn)單地傳遞訂閱者的名字給 subscribe 方法就可以做到:

Event::subscribe('UserEventHandler');