äº‹ä»¶ç®¡ç† ============== æ¤ç»„件的目的是通过创建挂钩点拦截框架ä¸å¤§éƒ¨åˆ†ç»„件的执行。这些挂钩点å…许开å‘者获å–状æ€ä¿¡æ¯ï¼Œæ“ä½œæ•°æ®æˆ–改å˜ä¸€ä¸ªç»„件在执行过程ä¸çš„æµç¨‹ã€‚ 译者注:挂钩点(hooks point)类似于SVN或GITä¸çš„hook。在使用SVNå¼€å‘过程ä¸ï¼Œæˆ‘们想实现把æäº¤çš„代ç 直接部署到演示环境下,那么就需è¦SVNçš„hook. 使用示例 ------------- 在下é¢çš„例åä¸ï¼Œæˆ‘们使用EventsManager侦å¬ä½¿ç”¨ :doc:`Phalcon\\Db <../api/Phalcon_Db>` 进行MySQL连接管ç†è¿‡ç¨‹ä¸äº§ç”Ÿçš„事件。首先,我们需è¦ä¸€ä¸ªä¾¦å¬å™¨å¯¹è±¡ï¼Œæˆ‘们创建一个类,它的方法是我们è¦ä¾¦å¬çš„事件: .. code-block:: php <?php class MyDbListener { public function afterConnect() { } public function beforeQuery() { } public function afterQuery() { } } 这个新的类文件å¯ä»¥æ›´è¯¦ç»†ä¸€äº›ï¼Œå› 为我们需è¦ä½¿ç”¨å®ƒã€‚EventsManager 将充当组件与侦å¬å™¨ä¹‹é—´çš„æ¡¥æ¢ï¼Œä¸ºæˆ‘们创建的侦å¬ç±»çš„æ–¹æ³•æä¾›æŒ‚钩点: .. code-block:: php <?php $eventsManager = new \Phalcon\Events\Manager(); //Create a database listener $dbListener = new MyDbListener() //Listen all the database events $eventsManager->attach('db', $dbListener); $connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array( "host" => "localhost", "username" => "root", "password" => "secret", "dbname" => "invo" )); //Assign the eventsManager to the db adapter instance $connection->setEventsManager($eventsManager); //Send a SQL command to the database server $connection->query("SELECT * FROM products p WHERE p.status = 1"); ä¸ºäº†è®°å½•æˆ‘ä»¬çš„åº”ç”¨ç¨‹åºæ‰§è¡Œçš„æ‰€æœ‰SQLè¯å¥ï¼Œæˆ‘们需è¦ä½¿ç”¨äº‹ä»¶â€œafterQueryâ€ã€‚ç¬¬ä¸€ä¸ªå‚æ•°ä¼ 递给 事件侦å¬å™¨ï¼ŒåŒ…嫿£åœ¨è¿è¡Œçš„事件的上下文信æ¯ï¼Œç¬¬äºŒä¸ªæ˜¯è¿žæŽ¥æœ¬èº«ã€‚ .. code-block:: php <?php class MyDbListener { protected $_logger; public function __construct() { $this->_logger = new \Phalcon\Logger\Adapter\File("../apps/logs/db.log"); } public function afterQuery($event, $connection) { $this->_logger->log($connection->getSQLStatement(), \Phalcon\Logger::INFO); } } 作为示例的一部分,我们需è¦å®žçް Phalcon\\Db\\Profiler,以检测SQLè¯å¥æ¯”预期花费多长时间: .. code-block:: php <?php class MyDbListener { protected $_profiler; protected $_logger; public function __construct() { $this->_profiler = new \Phalcon\Db\Profiler(); $this->_logger = new \Phalcon\Logger\Adapter\File("../apps/logs/db.log"); } public function beforeQuery($event, $connection) { $this->_profiler->startProfile($connection->getSQLStatement()); } public function afterQuery($event, $connection) { $this->_logger->log($connection->getSQLStatement(), \Phalcon\Logger::INFO); $this->_profiler->stopProfile(); } public function getProfiler() { return $this->_profiler; } } å¯ä»¥ä»Žç›‘å¬å™¨èŽ·å¾—è¿”å›žçš„æ•°æ®ï¼š .. code-block:: php <?php //Send a SQL command to the database server $connection->query("SELECT * FROM products p WHERE p.status = 1"); foreach($dbListener->getProfiler()->getProfiles() as $profile){ echo "SQL Statement: ", $profile->getSQLStatement(), "\n"; echo "Start Time: ", $profile->getInitialTime(), "\n" echo "Final Time: ", $profile->getFinalTime(), "\n"; echo "Total Elapsed Time: ", $profile->getTotalElapsedSeconds(), "\n"; } 以类似的方å¼ï¼Œæˆ‘们å¯ä»¥æ³¨å†Œä¸€ä¸ªlambdaå½¢å¼çš„匿åå‡½æ•°æ¥æ‰§è¡Œä»»åŠ¡ï¼Œè€Œä¸æ˜¯ä¸€ä¸ªå•独的监å¬å™¨ç±»(è§ä¸Šé¢ç¤ºä¾‹): .. code-block:: php <?php //Listen all the database events $eventManager->attach('db', function($event, $connection) { if ($event->getType() == 'afterQuery') { echo $connection->getSQLStatement(); } }); Creating components that trigger Events --------------------------------------- ä½ ä¹Ÿå¯ä»¥åœ¨åº”用程åºä¸åˆ›å»ºè‡ªå·±çš„组件,使用EventsManager触å‘事件。作为结果,事件è¿è¡Œæ—¶ç›‘å¬å™¨ä¼šä½œå‡ºç›¸åº”çš„å应。在下é¢çš„例åä¸ï¼Œæˆ‘们创建了一个å«"MyComponent"的组件。这个组件实现了EventsManager aware接å£ï¼Œå½“它的方法 "someTask" 执行时,监å¬å™¨ä¼šè§¦å‘相应的两个事件: .. code-block:: php <?php class MyComponent implements \Phalcon\Events\EventsAwareInterface { protected $_eventsManager; public function setEventsManager($eventsManager) { $this->_eventsManager = $eventsManager; } public function getEventsManager() { return $this->_eventsManager } public function someTask() { $this->_eventsManager->fire("my-component:beforeSomeTask", $this); // do some task $this->_eventsManager->fire("my-component:afterSomeTask", $this); } } 请注æ„ï¼Œè¿™ä¸ªäº‹ä»¶åœ¨è§¦å‘æ—¶ä½¿ç”¨çš„å‰è¾æ˜¯ "my-component"ï¼Œè¿™æ˜¯ä¸€ä¸ªå”¯ä¸€æ ‡å¿—å—符,以帮助我们知é“äº‹ä»¶æ˜¯ç”±å“ªä¸ªç»„ä»¶äº§ç”Ÿçš„ã€‚ä½ ç”šè‡³å¯ä»¥åœ¨ç»„件之个创建相åŒå称的事件。现在,让我们æ¥åˆ›å»ºä¸€ä¸ªç›‘å¬å™¨ç›‘å¬è¿™ä¸ªç»„件: .. code-block:: php <?php class SomeListener { public function beforeSomeTask($event, $myComponent) { echo "Here, beforeSomeTask\n"; } public function afterSomeTask($event, $myComponent) { echo "Here, afterSomeTask\n"; } } 一个监å¬å™¨å°±æ˜¯ä¸€ä¸ªç®€å•的类文件,它实现了所有组件触å‘的事件。现在,让我们使他们è”åˆåœ¨ä¸€èµ·å·¥ä½œï¼š .. code-block:: php <?php //Create an Events Manager $eventsManager = new Phalcon\Events\Manager(); //Create the MyComponent instance $myComponent = new MyComponent(); //Bind the eventsManager to the instance $myComponent->setEventsManager($myComponent); //Attach the listener to the EventsManager $eventsManager->attach('my-component', new SomeListener()); //Execute methods in the component $myComponent->someTask(); "someTask"执行åŽï¼Œç›‘å¬å™¨ä¸çš„ä¸¤ä¸ªæ–¹æ³•ä¹Ÿä¼šè¢«æ‰§è¡Œï¼Œä¸‹é¢æ˜¯è¾“出结果: .. code-block:: php Here, beforeSomeTask Here, afterSomeTask å…¶ä»–æ•°æ®ä¹Ÿå¯ä»¥é€šè¿‡ "fire" è°ƒç”¨ç¬¬ä¸‰ä¸ªå‚æ•°è¿›è¡Œè§¦å‘: .. code-block:: php <?php $eventsManager->fire("my-component:afterSomeTask", $this, $extraData); 在监å¬å™¨ä¸ï¼Œç¬¬ä¸‰ä¸ªå‚æ•°ä¹ŸæŽ¥æ”¶æ¤æ•°æ®ï¼š .. code-block:: php <?php //Receiving the data in the third parameter $eventManager->attach('my-component', function($event, $component, $data) { print_r($data); }); //Receiving the data from the event context $eventManager->attach('my-component', function($event, $component) { print_r($event->getData()); }); 如果监å¬å™¨åªå¯¹ä¸€ä¸ªç‰¹å®šç±»åž‹çš„äº‹ä»¶æ„Ÿå…´è¶£ï¼Œä½ å¯ä»¥ç›´æŽ¥ç»‘定: .. code-block:: php <?php //The handler will only be executed if the event triggered is "beforeSomeTask" $eventManager->attach('my-component:beforeSomeTask', function($event, $component) { //... }); 事件的å‘å¸ƒä¸Žå–æ¶ˆ(Event Propagation/Cancelation) ------------------------------------------------------------------ 许多监å¬å™¨å¯èƒ½ä¼šæ·»åŠ ç›¸åŒçš„事件,这æ„味ç€ï¼Œå¯¹äºŽåŒç±»ç±»åž‹çš„事件,许多监å¬å™¨éƒ½ä¼šè¢«è§¦å‘(å³ä¼šæœ‰éžå¸¸å¤šåŒç±»åž‹çš„æ¶ˆæ¯è¾“出)ã€‚æ ¹æ®æ³¨å†Œåˆ° EventsManager 的顺åºï¼Œç›‘å¬å™¨è¢«ä¸€ä¸€è§¦å‘。一些事件å¯ä»¥è¢«æ’¤æ¶ˆï¼Œè¡¨æ˜Žå¯ä»¥åœæ¢ä¸€äº›å…¶ä»–的监å¬å™¨äº‹ä»¶è¢«è§¦å‘: .. code-block:: php <?php $eventsManager->attach('db', function($event, $connection){ //We stop the event if it is cancelable if ($event->isCancelable()) { //Stop the event, so other listeners will not be notified about this $event->stop(); } //... }); 在默认情况下,事件是å¯ä»¥è¢«å–消的,甚至在框架ä¸çš„大部分事件都是å¯ä»¥è¢«å–æ¶ˆçš„ã€‚ä½ å¯ä»¥ä½¿ç”¨fireæ–¹æ³•ä¼ é€’ç¬¬å››ä¸ªå‚æ•°ï¼Œå€¼ä¸º"false",以达到ä¸å¯å–消的目的: .. code-block:: php <?php $eventsManager->fire("my-component:afterSomeTask", $this, $extraData, false); 实现自定义EventsManager(Implementing your own EventsManager) --------------------------------------------------------------------------- The :doc:`Phalcon\\Events\\ManagerInterface <../api/Phalcon_Events_ManagerInterface>` interface must be implemented to create your own EventsManager replacing the one provided by Phalcon.