# 事件管理器(Events Manager)
此組件的目的是為了通過創建“鉤子”攔截框架中大部分的組件操作。 這些鉤子允許開發者獲得狀態信息,操縱數據或者改變某個組件進程中的執行流向。
## Naming Convention
Phalcon events use namespaces to avoid naming collisions. Each component in Phalcon occupies a different event namespace and you are free to create your own as you see fit. Event names are formatted as “component:event”. For example, as[Phalcon\\Db](http://docs.iphalcon.cn/api/Phalcon_Db.html)occupies the “db” namespace, its “afterQuery” event’s full name is “db:afterQuery”.
When attaching event listeners to the events manager, you can use “component” to catch all events from that component (eg. “db” to catch all of the[Phalcon\\Db](http://docs.iphalcon.cn/api/Phalcon_Db.html)events) or “component:event” to target a specific event (eg. “db:afterQuery”).
## 使用示例(Usage Example)
In the following example, we will use the EventsManager to listen for the “afterQuery” event produced in a MySQL connection managed by[Phalcon\\Db](http://docs.iphalcon.cn/api/Phalcon_Db.html):
~~~
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
$eventsManager = new EventsManager();
$eventsManager->attach(
"db:afterQuery",
function (Event $event, $connection) {
echo $connection->getSQLStatement();
}
);
$connection = new DbAdapter(
[
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo",
]
);
// 將$eventsManager賦值給數據庫甜適配器
$connection->setEventsManager($eventsManager);
// 發送一個SQL命令到數據庫服務器
$connection->query(
"SELECT * FROM products p WHERE p.status = 1"
);
~~~
Now every time a query is executed, the SQL statement will be echoed out. 第一個傳遞給事件偵聽者的參數包含了關于正在運行事件的上下文信息,第二個則是連接本身。 A third parameter may also be specified which will contain arbitrary data specific to the event.
> You must explicitly set the Events Manager to a component using the`setEventsManager()`method in order for that component to trigger events. You can create a new Events Manager instance for each component or you can set the same Events Manager to multiple components as the naming convention will avoid conflicts.
Instead of using lambda functions, you can use event listener classes instead. Event listeners also allow you to listen to multiple events. 作為些示例的一部分,我們同樣實現了[Phalcon\\Db\\Profiler](http://docs.iphalcon.cn/api/Phalcon_Db_Profiler.html)來檢測SQL語句是否超出了期望的執行時間:
~~~
<?php
use Phalcon\Db\Profiler;
use Phalcon\Events\Event;
use Phalcon\Logger;
use Phalcon\Logger\Adapter\File;
class MyDbListener
{
protected $_profiler;
protected $_logger;
/**
*創建分析器并開始紀錄
*/
public function __construct()
{
$this->_profiler = new Profiler();
$this->_logger = new Logger("../apps/logs/db.log");
}
/**
* 如果事件觸發器是'beforeQuery',此函數將會被執行
*/
public function beforeQuery(Event $event, $connection)
{
$this->_profiler->startProfile(
$connection->getSQLStatement()
);
}
/**
* 如果事件觸發器是'afterQuery',此函數將會被執行
*/
public function afterQuery(Event $event, $connection)
{
$this->_logger->log(
$connection->getSQLStatement(),
Logger::INFO
);
$this->_profiler->stopProfile();
}
public function getProfiler()
{
return $this->_profiler;
}
}
~~~
Attaching an event listener to the events manager is as simple as:
~~~
<?php
// 創建一個數據庫偵聽
$dbListener = new MyDbListener();
// 偵聽全部數據庫事件
$eventsManager->attach(
"db",
$dbListener
);
~~~
可以從偵聽者中獲取結果分析數據:
~~~
<?php
// 發送一個SQL命令到數據庫服務器
$connection->execute(
"SELECT * FROM products p WHERE p.status = 1"
);
foreach ($dbListener->getProfiler()->getProfiles() as $profile) {
echo "SQL語句: ", $profile->getSQLStatement(), "\n";
echo "開始時間: ", $profile->getInitialTime(), "\n";
echo "結束時間: ", $profile->getFinalTime(), "\n";
echo "總共執行的時間: ", $profile->getTotalElapsedSeconds(), "\n";
}
~~~
## 創建組件觸發事件(Creating components that trigger Events)
你可以在你的應用中為事件管理器的觸發事件創建組件。這樣的結果是,可以有很多存在的偵聽者為這些產生的事件作出響應。 在以下的示例中,我們將會創建一個叫做“MyComponent”組件。這是個意識事件管理器組件; 當它的方法:code:[`](http://docs.iphalcon.cn/reference/events.html#id1)someTask()`被執行時它將觸發事件管理器中全部偵聽者的兩個事件:
~~~
<?php
use Phalcon\Events\ManagerInterface;
use Phalcon\Events\EventsAwareInterface;
class MyComponent implements EventsAwareInterface
{
protected $_eventsManager;
public function setEventsManager(ManagerInterface $eventsManager)
{
$this->_eventsManager = $eventsManager;
}
public function getEventsManager()
{
return $this->_eventsManager;
}
public function someTask()
{
$this->_eventsManager->fire("my-component:beforeSomeTask", $this);
// 做一些你想做的事情
echo "這里, someTask\n";
$this->_eventsManager->fire("my-component:afterSomeTask", $this);
}
}
~~~
Notice that in this example, we’re using the “my-component” event namespace. 現在讓我們來為這個組件創建一個偵聽者:
~~~
<?php
use Phalcon\Events\Event;
class SomeListener
{
public function beforeSomeTask(Event $event, $myComponent)
{
echo "這里, beforeSomeTask\n";
}
public function afterSomeTask(Event $event, $myComponent)
{
echo "這里, afterSomeTask\n";
}
}
~~~
現在讓我們把全部的東西整合起來:
~~~
<?php
use Phalcon\Events\Manager as EventsManager;
// 創建一個事件管理器
$eventsManager = new EventsManager();
// 創建MyComponent實例
$myComponent = new MyComponent();
// 將事件管理器綁定到創建MyComponent實例實例
$myComponent->setEventsManager($eventsManager);
// 為事件管理器附上偵聽者
$eventsManager->attach(
"my-component",
new SomeListener()
);
// 執行組件的方法
$myComponent->someTask();
~~~
當:code:[`](http://docs.iphalcon.cn/reference/events.html#id3)someTask()`被執行時,在偵聽者里面的兩個方法將會被執行,并產生以下輸出:
~~~
這里, beforeSomeTask
這里, someTask
這里, afterSomeTask
~~~
當觸發一個事件時也可以使用:code:[`](http://docs.iphalcon.cn/reference/events.html#id5)fire()`中的第三個參數來傳遞額外的數據:
~~~
<?php
$eventsManager->fire("my-component:afterSomeTask", $this, $extraData);
~~~
在一個偵聽者里,第三個參數可用于接收此參數:
~~~
<?php
use Phalcon\Events\Event;
// 從第三個參數接收數據
$eventsManager->attach(
"my-component",
function (Event $event, $component, $data) {
print_r($data);
}
);
// 從事件上下文中接收數據
$eventsManager->attach(
"my-component",
function (Event $event, $component) {
print_r($event->getData());
}
);
~~~
## Using Services From The DI
By extending[Phalcon\\Mvc\\User\\Plugin](http://docs.iphalcon.cn/api/Phalcon_Mvc_User_Plugin.html), you can access services from the DI, just like you would in a controller:
~~~
<?php
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
class SomeListener extends Plugin
{
public function beforeSomeTask(Event $event, $myComponent)
{
echo "Here, beforeSomeTask\n";
$this->logger->debug(
"beforeSomeTask has been triggered";
);
}
public function afterSomeTask(Event $event, $myComponent)
{
echo "Here, afterSomeTask\n";
$this->logger->debug(
"afterSomeTask has been triggered";
);
}
}
~~~
## 事件傳播與取消(Event Propagation/Cancellation)
可能會有多個偵聽者添加到同一個事件管理器,這意味著對于相同的事件會通知多個偵聽者。 這些偵聽者會以它們在事件管理器注冊的順序來通知。有些事件是可以被取消的,暗示著這些事件可以被終止以防其他偵聽都再收到事件的通知:
~~~
<?php
use Phalcon\Events\Event;
$eventsManager->attach(
"db",
function (Event $event, $connection) {
// 如果可以取消,我們就終止此事件
if ($event->isCancelable()) {
// 終止事件,這樣的話其他偵聽都就不會再收到此通知
$event->stop();
}
// ...
}
);
~~~
默認情況下全部的事件都是可以取消的,甚至框架提供的事件也是可以取消的。 你可以通過在`fire()`中的第四個參數中傳遞`false`來指明這是一個不可取消的事件:
~~~
<?php
$eventsManager->fire("my-component:afterSomeTask", $this, $extraData, false);
~~~
## 偵聽器優先級(Listener Priorities)
當附上偵聽者時,你可以設置一個優先級。使用此特性,你可以指定這些偵聽者被調用的固定順序:
~~~
<?php
$eventsManager->enablePriorities(true);
$eventsManager->attach("db", new DbListener(), 150); // 高優先級
$eventsManager->attach("db", new DbListener(), 100); // 正常優先級
$eventsManager->attach("db", new DbListener(), 50); // 低優先級
~~~
## 收集響應(Collecting Responses)
事件管理器可以收集每一個被通知的偵聽者返回的響應,以下這個示例解釋了它是如何工作的:
~~~
<?php
use Phalcon\Events\Manager as EventsManager;
$eventsManager = new EventsManager();
// 建立事件管理器以為收集結果響應
$eventsManager->collectResponses(true);
// 附上一個偵聽者
$eventsManager->attach(
"custom:custom",
function () {
return "first response";
}
);
// 附上一個偵聽者
$eventsManager->attach(
"custom:custom",
function () {
return "second response";
}
);
// 執行fire事件
$eventsManager->fire("custom:custom", null);
// 獲取全部收集到的響應
print_r($eventsManager->getResponses());
~~~
上面示例將輸出:
~~~
Array ( [0] => first response [1] => second response )
~~~
## 自定義事件管理器(Implementing your own EventsManager)
如果想要替換Phalcon提供的事件管理器,必須實現[Phalcon\\Events\\ManagerInterface](http://docs.iphalcon.cn/api/Phalcon_Events_ManagerInterface.html)中的接口。
- 簡介
- 安裝
- 安裝(installlation)
- XAMPP下的安裝
- WAMP下安裝
- Nginx安裝說明
- Apache安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- 教程
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: V?kuró
- 教程 7:創建簡單的 REST API
- 組件
- 依賴注入與服務定位器
- MVC架構
- 使用控制器
- 使用模型
- 模型關系
- 事件與事件管理器
- Behaviors
- 模型元數據
- 事務管理
- 驗證數據完整性
- Workingwith Models
- Phalcon查詢語言
- 緩存對象關系映射
- 對象文檔映射 ODM
- 使用視圖
- 視圖助手
- 資源文件管理
- Volt 模版引擎
- MVC 應用
- 路由
- 調度控制器
- Micro Applications
- 使用命名空間
- 事件管理器
- Request Environmen
- 返回響應
- Cookie 管理
- 生成 URL 和 路徑
- 閃存消息
- 使用 Session 存儲數據
- 過濾與清理
- 上下文編碼
- 驗證Validation
- 表單_Forms
- 讀取配置
- 分頁 Pagination
- 使用緩存提高性能
- 安全
- 加密與解密 Encryption/Decryption
- 訪問控制列表
- 多語言支持
- 類加載器 Class Autoloader
- 日志記錄_Logging
- 注釋解析器 Annotations Parser
- 命令行應用 Command Line Applications
- Images
- 隊列 Queueing
- 數據庫抽象層
- 國際化
- 數據庫遷移
- 調試應用程序
- 單元測試
- 進階技巧與延伸閱讀
- 提高性能:下一步該做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl