tp6事件的用法
新版的事件系統(tǒng)可以看成是5.1版本行為系統(tǒng)的升級版,事件系統(tǒng)相比行為系統(tǒng)強大的地方在于事件本身可以是一個類,并且可以更好的支持事件訂閱者。
事件相比較中間件的優(yōu)勢是事件比中間件更加精準定位(或者說粒度更細),并且更適合一些業(yè)務(wù)場景的擴展。例如,我們通常會遇到用戶注冊或者登錄后需要做一系列操作,通過事件系統(tǒng)可以做到不侵入原有代碼完成登錄的操作擴展,降低系統(tǒng)的耦合性的同時,也降低了BUG的可能性。
事件系統(tǒng)的所有操作都通過think\facade\Event類進行靜態(tài)調(diào)用
定義事件
事件系統(tǒng)使用了觀察者模式,提供了解耦應(yīng)用的更好方式。在你需要監(jiān)聽事件的位置,例如下面我們在用戶完成登錄操作之后添加如下事件觸發(fā)代碼:
// 觸發(fā)UserLogin事件 用于執(zhí)行用戶登錄后的一系列操作 Event::trigger('UserLogin');或者使用助手函數(shù)
event('UserLogin');這里UserLogin表示一個事件標識,如果你定義了單獨的事件類,你可以使用事件類名(甚至可以傳入一個事件類實例)。
// 直接使用事件類觸發(fā) event('app\event\UserLogin');事件類可以通過命令行快速生成
php think make:event UserLogin默認會生成一個app\event\UserLogin事件類,也可以指定完整類名生成。
我們可以給事件類添加方法
namespace app\event;use app\model\User;class UserLogin {public $user;public function __construct(User $user){$this->user = $user;} }一般事件類無需繼承任何其它類。
你可以給事件類綁定一個事件標識,一般建議直接在應(yīng)用的event.php事件定義文件中批量綁定。
return ['bind' => ['UserLogin' => 'app\event\UserLogin',// 更多事件綁定], ];如果你需要動態(tài)綁定,可以使用
Event::bind(['UserLogin' => 'app\event\UserLogin']);ThinkPHP的事件系統(tǒng)不依賴事件類,如果沒有額外的需求,僅通過事件標識也可以使用,省去定義事件類的麻煩。
如果你沒有定義事件類的話,則無需綁定。對于大部分的場景,可能確實不需要定義事件類。
你可以在event方法中傳入一個事件參數(shù)
// user是當前登錄用戶對象實例 event('UserLogin', $user);事件監(jiān)聽
你可以手動注冊一個事件監(jiān)聽
Event::listen('UserLogin', function($user) {// });或者使用監(jiān)聽類來執(zhí)行監(jiān)聽
Event::listen('UserLogin', 'app\listener\UserLogin');可以通過命令行快速生成一個事件監(jiān)聽類
php think make:listener UserLogin默認會生成一個app\listener\UserLogin事件監(jiān)聽類,也可以指定完整類名生成。
事件監(jiān)聽類只需要定義一個handle方法,支持依賴注入。
<?php namespace app\listener;class UserLogin {public function handle($user){// 事件監(jiān)聽處理} }在handle方法中如果返回了false,則表示監(jiān)聽中止,將不再執(zhí)行該事件后面的監(jiān)聽。
一般建議直接在事件定義文件中定義對應(yīng)事件的監(jiān)聽。
return ['bind' => ['UserLogin' => 'app\event\UserLogin',// 更多事件綁定],'listen' => ['UserLogin' => ['app\listener\UserLogin'],// 更多事件監(jiān)聽], ];事件訂閱
可以通過事件訂閱機制,在一個監(jiān)聽器中監(jiān)聽多個事件,例如通過命令行生成一個事件訂閱者類,
php think make:subscribe User默認會生成app\subscribe\User類,或者你可以指定完整類名生成。
然后你可以在事件訂閱類中添加不同事件的監(jiān)聽方法,例如。
<?php namespace app\subscribe;class User {public function onUserLogin($user){// UserLogin事件響應(yīng)處理}public function onUserLogout($user){// UserLogout事件響應(yīng)處理} }監(jiān)聽事件的方法命名規(guī)范是on+事件標識(駝峰命名),如果希望統(tǒng)一添加事件前綴標識,可以定義eventPrefix屬性。
<?php namespace app\subscribe;class User {protected $eventPrefix = 'User';public function onLogin($user){// UserLogin事件響應(yīng)處理}public function onLogout($user){// UserLogout事件響應(yīng)處理} }如果希望自定義訂閱方式(或者方法規(guī)范),可以定義subscribe方法實現(xiàn)。
<?php namespace app\subscribe;use think\Event;class User {public function onUserLogin($user){// UserLogin事件響應(yīng)處理}public function onUserLogout($user){// UserLogout事件響應(yīng)處理}public function subscribe(Event $event){$event->listen('UserLogin', [$this,'onUserLogin']);$event->listen('UserLogout',[$this,'onUserLogout']);} }然后在事件定義文件注冊事件訂閱者
return ['bind' => ['UserLogin' => 'app\event\UserLogin',// 更多事件綁定],'listen' => ['UserLogin' => ['app\listener\UserLogin'],// 更多事件監(jiān)聽],'subscribe' => ['app\subscribe\User',// 更多事件訂閱], ];如果需要動態(tài)注冊,可以使用
Event::subscribe('app\subscribe\User');內(nèi)置事件
內(nèi)置的系統(tǒng)事件包括:
| AppInit | 應(yīng)用初始化標簽位 | 無 |
| HttpRun | 應(yīng)用開始標簽位 | 無 |
| HttpEnd | 應(yīng)用結(jié)束標簽位 | 當前響應(yīng)對象實例 |
| LogWrite | 日志write方法標簽位 | 當前寫入的日志信息 |
| RouteLoaded | 路由加載完成 | 無 |
AppInit事件定義必須在全局事件定義文件中定義,其它事件支持在應(yīng)用的事件定義文件中定義。
原來5.1的一些行為標簽已經(jīng)廢棄,所有取消的標簽都可以使用中間件更好的替代。可以把中間件看成處理請求以及響應(yīng)輸出相關(guān)的特殊事件。事實上,中間件的handler方法只是具有特殊的參數(shù)以及返回值而已。
數(shù)據(jù)庫操作的回調(diào)也稱為查詢事件,是針對數(shù)據(jù)庫的CURD操作而設(shè)計的回調(diào)方法,主要包括:
| before_select | select查詢前回調(diào) |
| before_find | find查詢前回調(diào) |
| after_insert | insert操作成功后回調(diào) |
| after_update | update操作成功后回調(diào) |
| after_delete | delete操作成功后回調(diào) |
查詢事件的參數(shù)就是當前的查詢對象實例。
模型事件包含:
| after_read | 查詢后 |
| before_insert | 新增前 |
| after_insert | 新增后 |
| before_update | 更新前 |
| after_update | 更新后 |
| before_write | 寫入前 |
| after_write | 寫入后 |
| before_delete | 刪除前 |
| after_delete | 刪除后 |
before_write和after_write事件無論是新增還是更新都會執(zhí)行
實際項目案例代碼:完整項目 http://github.crmeb.net/u/lingting 開源項目,使用TP6框架開發(fā)的
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK ] // +---------------------------------------------------------------------- // | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: liu21st <liu21st@gmail.com> // +----------------------------------------------------------------------// 事件定義文件 return ['bind' => [],'listen' => ['AppInit' => [],'HttpRun' => [],'HttpEnd' => [],'LogLevel' => [],'LogWrite' => [],'task_2'=>[],//2秒鐘執(zhí)行的方法'task_6'=>[],//6秒鐘執(zhí)行的方法'task_10'=>[],//10秒鐘執(zhí)行的方法'task_30'=>[],//30秒鐘執(zhí)行的方法'task_60'=>[],//60秒鐘執(zhí)行的方法'task_180'=>[],//180秒鐘執(zhí)行的方法'task_300'=>[],//300秒鐘執(zhí)行的方法'StoreProductOrderDeliveryAfter' => [], // OrderSubscribe 送貨 發(fā)送模板消息 admin模塊 order.StoreOrder控制器/order.combinationOrder控制器'StoreProductOrderDeliveryGoodsAfter' => [], // OrderSubscribe 發(fā)貨 發(fā)送模板消息 admin模塊 order.StoreOrder控制器/order.combinationOrder控制器'StoreProductOrderRefundNAfter' => [], // OrderSubscribe 訂單狀態(tài)不退款 發(fā)送模板消息 admin模塊 order.StoreOrder控制器/order.combinationOrder控制器'StoreProductOrderOffline' => [], // OrderSubscribe 線下付款成功后 admin模塊 order.StoreOrder控制器/order.combinationOrder控制器'StoreProductOrderEditAfter' => [], // OrderSubscribe 修改訂單金額 admin模塊 order.StoreOrder控制器/order.combinationOrder控制器'StoreProductOrderDistributionAfter' => [], // OrderSubscribe 修改配送信息 admin模塊 order.StoreOrder控制器/order.combinationOrder控制器'StoreProductOrderOver' => [], // OrderSubscribe 訂單全部產(chǎn)品評價完 models模塊 store.StoreOrder Model'StoreOrderRegressionAllAfter' => [], // OrderSubscribe 回退所有 未支付和已退款的狀態(tài)下才可以退積分退庫存退優(yōu)惠券 models模塊 store.StoreOrder Model'AdminVisit' => [], // SystemSubscribe 添加管理員訪問記錄 admin模塊 AuthController控制器'SystemAdminLoginAfter' => [], // SystemSubscribe 添加管理員最后登錄時間和ip 添加管理員訪問記錄 admin模塊 system.SystemAdmin控制器'StoreProductSetCartAfter' => [], // ProductSubscribe 加入購物車成功之后 wap模塊 AuthApi控制器'StoreProductUserOperationConfirmAfter' => [], // ProductSubscribe 用戶操作產(chǎn)品添加事件 用戶點贊產(chǎn)品 用戶收藏產(chǎn)品 Models模塊 store.StoreProductRelation Model'StoreProductUserOperationCancelAfter' => [], // ProductSubscribe 用戶操作產(chǎn)品取消事件 用戶取消點贊產(chǎn)品 用戶取消收藏產(chǎn)品 Models模塊 store.StoreProductRelation Model'WechatMaterialAfter' => [], // MaterialSubscribe 微信公眾號 圖片/聲音 轉(zhuǎn)media 存入數(shù)據(jù)庫 admin模塊 wechat.WechatReplyModel'WechatMessageBefore' => [], // MessageSubscribe 微信消息前置操作 crmeb\services\WechatService'WechatEventUnsubscribeBefore' => [], // MessageSubscribe 用戶取消關(guān)注公眾號前置操作 crmeb\services\WechatService'WechatOauthAfter' => [], // UserSubscribe 微信授權(quán)成功后 wap模塊 WapBasic控制器'InitLogin' => [], // UserSubscribe 微信授權(quán)成功后 ebapi模塊 Basic控制器'UserLevelAfter' => [], // UserSubscribe 檢查是否能成為會員 models模塊 user.UserSign Model store.StoreOrder Model user.UserBill Model'OrderCreated' => [], //用戶訂單創(chuàng)建成功'OrderPaySuccess' => [], //用戶訂單支付成功'OrderCreateAgain' => [], //用戶再次下單'UserOrderRemoved' => [], //用戶刪除訂單'UserOrderTake' => [], //用戶確認收貨'UserCommented' => [], //用戶評價商品'RechargeSuccess' => [], //用戶充值成功后'ImportNowMoney' => [], //用戶傭金轉(zhuǎn)成余額成功后],'subscribe' => [crmeb\subscribes\SystemSubscribe::class,crmeb\subscribes\OrderSubscribe::class,crmeb\subscribes\ProductSubscribe::class,crmeb\subscribes\UserSubscribe::class,crmeb\subscribes\MaterialSubscribe::class,crmeb\subscribes\MessageSubscribe::class,crmeb\subscribes\TaskSubscribe::class,], ];?
與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖總結(jié)
- 上一篇: 有人能和我说说,多特瑞精油怎么样吗?
- 下一篇: 黔是哪里 介绍贵州省的地理位置和特色?