2015/12/21

Codeigniter 整合 Symfony event dispatcher

我是參考此篇文章 http://codeigniter.org.cn/forums/thread-15598-1-1.html
補上一些我自己實作的步驟跟心得

[環境] 

Codeigniter 3.0.3

[步驟] 

  1. 安裝Composer(略 
  2. 安裝symfony/event-dispatcher (Packagist
  3. 設定CI使用composer 
  4. 設定composer autoload PSR-4 
  5. 新增CI Hook 讓 Controller 實例後執行事件註冊 
  6. 實作Symfony EventDispatcher 與 Event 
  7. 在CI Controller建立Event Dispatcher 
  8. 呼叫Event  



 [Event呼叫流程] 

1.application/conf/listeners.php 註冊需要的event listener物件
2.event listener物件註冊監聽事件與觸發方法
3.執行 EventDispatcher->dispatch() 觸發事件

 [開始啦!]  

2.安裝symfony/event-dispatcher 


在CI\Application下打 composer require symfony/event-dispatcher
等待它安裝完成,application目錄會增加vendor資料夾

3.設定CI使用composer 

application\config\config.php: 139
$config['composer_autoload'] = TRUE;

如果composer不是安裝在application下,TRUE請改成autoload.php的路徑

4.設定composer autoload PSR-4 

application\composer.json:

意思是讓 namespace App對應到目前的 application資料夾
App可以自己取

5.新增CI Hook 讓 Controller 實例後執行事件註冊

這裡步驟很多 拆開來寫

5.1設定CI使用Hook
application\config\config.php: 103
$config['enable_hooks'] = TRUE;

5.2 註冊CI Hook
application\config\hook.php: 103

post_controller_constructor是讓controller建立後,但還沒呼叫任何方法之前呼叫EventDispatcher的postControllerConstructor方法

其他的hook事件請參考Manual

5.3  post controller Hook
建立 application\hook\EventDispatcher.php

這邊的EventDispatcher請不要跟Symfony的搞混,只是告訴CI在controller生成時要來這邊執行。
這邊主要用途在註冊application/config/listener.php裡設定的EventDispatcher物件,之後不太會動到。

5.4 新增 listener config
application/config/listeners.php

單純一個陣列存放需要的EventListener
前面的 App\Events\Listeners\ 是我自己建立的namespace,
把它當成目錄想比較簡單,由於在composer psr-4已經設定 App 會對應到 application資料夾,
所以這串就是要去 new 一個在 application\events\listeners 目錄裡的 class UserEventListener。

6. 實作Symfony EventDispatcher 與 Event

我把所有的Event Class都放在application\events底下,沒特別說明都是在這裏面

處理使用者東西的事件 UserEventListener


UserEvent 為dispatch傳來的參數,需要繼承自Event


請注意這兩隻檔案的namespace要對應所在的位置
不然PHP會噴找不到檔案的訊息

註: 這時候開網頁還是會噴not found,因為還沒更新composer autoload

7.在CI Controller建立Event Dispatcher


因為Hook會去存取每個controller的dispatcher的屬性,
需要再construct時先new EventDispatcher,
不然會跳錯誤。
EventDispatcher是Symfony的,請記得用 use 來指名。

但是每隻Controller都要寫一樣的construct太麻煩(如果只有幾隻就算了)
所以把這段code放到另個Controller,讓其他controller去繼承它

7.1 建立MY_Controller
建立 application\core\MY_Controller.php


然後把原來的Controller extends MY_Controller


沒有跳錯誤就表示成功啦~

8.呼叫Event 


就呼叫dispatcher的dispatch方法
第一個是事件名稱,是在UserEventListener->getSubscribedEvents() 定義的
會把第二個參數(這裡是UserEvent實例) 丟進 UserEventListener->onRegistered() 裡

註:
這邊執行會出現錯誤訊息 "Undefined variable: user"
因為我在Controller沒有傳 $user 給 UserEvent,執行時找不到所以噴訊息。


[使用事件的好處]
以使用者註冊舉例,通常在使用者註冊完後都需要做一堆事情
比如發送歡迎信件、建立個人Profile或空間、通知管理者有新使用者、寫入系統紀錄之類的

通常都會把它放進controller裡面,類似

如果都是用物件這樣寫還蠻整齊的,如果是直接code在這裡
這個method就會至少兩百行跑不掉

況且,如果今天要增加/修改這些行為,每次都得編輯這個controller
(controller表示: 關我屁事....)

那,是不是有方法可以讓我"通知"系統有個使用者註冊就好
需要處理的程式接到通知就自己把工作做完不是很好?

於是Controller就只要這樣


然後新增其他的eventListener

這樣就會只要監聽到user_registered的服務就會自己做事情
Controller也不用管理這些東西
往後的增刪也非常容易


Source Code in GitHub

沒有留言:

張貼留言