swoft 事件監聽和觸發 列印sql日誌
阿新 • • 發佈:2020-07-17
需求 打印出swoft的所有sql日誌到控制檯或者檔案
只要開啟listener 下面 Dbranlisten.php 裡面最後一行註釋即可,swoft已經幫我們實現好了
____ _____ ___ ___ / __/ _____ / _/ /_ |_ | / _ \ _\ \| |/|/ / _ \/ _/ __/ / __/_/ // / /___/|__,__/\___/_/ \__/ /____(_)___/ SERVER INFORMATION(v2.0.9) ******************************************************************************** * HTTP | Listen: 0.0.0.0:18306, Mode: Process, Worker: 6, Task worker: 12 ******************************************************************************** HTTP Server Start Success! 2020/07/17-20:55:29 [INFO] Swoft\Server\Server:startSwoole(491) Swoole\Runtime::enableCoroutine 2020/07/17-20:55:29 [INFO] Swoft\Listener\BeforeStartListener:handle(27) Server extra info: pidFile @runtime/swoft.pid 2020/07/17-20:55:29 [INFO] Swoft\Listener\BeforeStartListener:handle(28) Registered swoole events: start, shutdown, managerStart, managerStop, workerStart, workerStop, workerError, request, task, finish Server start success (Master PID: 17681, Manager PID: 17686) [INFO] insert into `tb_users` (`name`, `age`, `created_at`) values ('test', 10, '2020-07-17 20:55:50')
為什麼會監聽到日誌 事件什麼時候觸發的
/**
* Class RanListener
*
* @since 2.0
*
* @Listener(DbEvent::SQL_RAN)
*/
/**
* Sql ran after
*/
public const SQL_RAN = 'swoft.db.ran';
全專案搜尋 DbEvent::SQL_RAN 發現除了呼叫的地方 還有寫入的地方
Connection.php /** * Run a SQL statement and log its execution context. * * @param string $query * @param array $bindings * @param Closure $callback * * @return mixed * * @throws DbException */ protected function run(string $query, array $bindings, Closure $callback) { $this->reconnectIfMissingConnection(); $start = microtime(true); // Here we will run this query. If an exception occurs we'll determine if it was // caused by a connection that has been lost. If that is the cause, we'll try $result = $this->runQueryCallback($query, $bindings, $callback); $time = $this->getElapsedTime($start); $this->fireEvent(DbEvent::SQL_RAN, $query, $bindings, $time); // Once we have run the query we will calculate the time that it took to run and // then log the query, bindings, and execution time so we will report them on // the event that the developer needs them. We'll log time in milliseconds. return $result; } 這個方法 $this->fireEvent(DbEvent::SQL_RAN, $query, $bindings, $time); 往下 HasEvent.php /** * Fire the given event for the model. * * @param string $event * @param mixed ...$args * * @return bool */ protected function fireEvent(string $event, ...$args): bool { // Trigger method public event $eventPublicResult = Swoft::trigger($event, $this, ...$args); if ($eventPublicResult->isPropagationStopped() === true) { return false; } // Not model no trigger if ($this->getContextName() !== 'model') { return true; } // Trigger model method event $modelEventResult = Swoft::trigger($this->getModelEventName($event), $this, ...$args); if ($modelEventResult->isPropagationStopped() === true) { return false; } return true; } 發現 Swoft::trigger($event, $this, ...$args); 往下 Swoft.php /** * Trigger an swoft application event * * @param string|EventInterface $event eg: 'app.start' 'app.stop' * @param null|mixed $target * @param array $params * * @return EventInterface */ public static function trigger($event, $target = null, ...$params): EventInterface { /** @see EventManager::trigger() */ return BeanFactory::getSingleton('eventManager')->trigger($event, $target, $params); } EventManage.php /** * Trigger an event. Can accept an EventInterface or will create one if not passed * * @param string|EventInterface $event 'app.start' 'app.stop' * @param mixed|string $target It is object or string. * @param array|mixed $args * * @return EventInterface * @throws InvalidArgumentException */ public function trigger($event, $target = null, array $args = []): EventInterface { if ($isString = is_string($event)) { $name = trim($event); } elseif ($event instanceof EventInterface) { $name = trim($event->getName()); } else { throw new InvalidArgumentException('Invalid event params for trigger event handler'); } $shouldCall = []; // Have matched listener if (isset($this->listenedEvents[$name])) { $shouldCall[$name] = ''; } // Like 'app.db.query' => prefix: 'app.db' if ($pos = strrpos($name, '.')) { $prefix = substr($name, 0, $pos); // Have a wildcards listener. eg 'app.db.*' $wildcardEvent = $prefix . '.*'; if (isset($this->listenedEvents[$wildcardEvent])) { $shouldCall[$wildcardEvent] = substr($name, $pos + 1); } } // Not found listeners if (!$shouldCall) { return $isString ? $this->basicEvent : $event; } /** @var EventInterface $event */ if ($isString) { $event = $this->events[$name] ?? $this->basicEvent; } // Initial value $event->setName($name); $event->setParams($args); $event->setTarget($target); $event->stopPropagation(false); // Notify event listeners foreach ($shouldCall as $name => $method) { $this->triggerListeners($this->listeners[$name], $event, $method); if ($event->isPropagationStopped()) { return $this->destroyAfterFire ? $event->destroy() : $event; } } // Have global wildcards '*' listener. if (isset($this->listenedEvents['*'])) { $this->triggerListeners($this->listeners['*'], $event); } return $this->destroyAfterFire ? $event->destroy() : $event; } 呼叫 triggerListeners /** * @param array|ListenerQueue $listeners * @param EventInterface $event * @param string $method */ protected function triggerListeners($listeners, EventInterface $event, string $method = ''): void { // $handled = false; $name = $event->getName(); $callable = false === strpos($name, '.'); // 迴圈呼叫監聽器,處理事件 foreach ($listeners as $listener) { if ($event->isPropagationStopped()) { break; } if (is_object($listener)) { if ($listener instanceof EventHandlerInterface) { $listener->handle($event); } elseif ($method && method_exists($listener, $method)) { $listener->$method($event); } elseif ($callable && method_exists($listener, $name)) { $listener->$name($event); } elseif (method_exists($listener, '__invoke')) { $listener($event); } } elseif (is_callable($listener)) { $listener($event); } } } 最終呼叫監聽的 hadle方法 所以是 調動trigger 就會觸發匹配到的監聽,執行監聽的hanle方法
模仿 自己觸發event 自己listen
控制器 HomeController 裡面新建方法
/** * @RequestMapping("/add") */ public function add() { // $user = new Users(); // $user->fill(['name'=>'test','age'=>10])->save(); // return $user; Swoft::trigger("swoft.wang","this is message",'hello','world'); }
app\Listener\Test\WangListener.php
<?php declare(strict_types=1); /** * This file is part of Swoft. * * @link https://swoft.org * @document https://swoft.org/docs * @contact [email protected] * @license https://github.com/swoft-cloud/swoft/blob/master/LICENSE */ namespace App\Listener\Test; use Swoft\Event\Annotation\Mapping\Listener; use Swoft\Event\EventHandlerInterface; use Swoft\Event\EventInterface; use Swoft\Exception\SwoftException; use Swoft\Log\Helper\CLog; use Swoft\Server\SwooleEvent; /** * Class ShutDownListener * * @since 2.0 * * @Listener("swoft.wang") */ class WangListener implements EventHandlerInterface { /** * @param EventInterface $event * * @throws SwoftException */ public function handle(EventInterface $event): void { $message = $event->getTarget(); $hello = $event->getParam(0); $world = $event->getParam(1); var_dump($message,$hello,$world); CLog::debug('this is a test trigger'); } }
訪問頁面 http://192.168.33.50:18306/add 發現結果為 如下 自己觸發的事件被自己監聽到了,打印出了引數
____ _____ ___ ___ / __/ _____ / _/ /_ |_ | / _ \ _\ \| |/|/ / _ \/ _/ __/ / __/_/ // / /___/|__,__/\___/_/ \__/ /____(_)___/ SERVER INFORMATION(v2.0.9) ******************************************************************************** * HTTP | Listen: 0.0.0.0:18306, Mode: Process, Worker: 6, Task worker: 12 ******************************************************************************** HTTP Server Start Success! 2020/07/17-21:06:09 [INFO] Swoft\Server\Server:startSwoole(491) Swoole\Runtime::enableCoroutine 2020/07/17-21:06:09 [INFO] Swoft\Listener\BeforeStartListener:handle(27) Server extra info: pidFile @runtime/swoft.pid 2020/07/17-21:06:09 [INFO] Swoft\Listener\BeforeStartListener:handle(28) Registered swoole events: start, shutdown, managerStart, managerStop, workerStart, workerStop, workerError, request, task, finish Server start success (Master PID: 17738, Manager PID: 17743) string(15) "this is message" string(5) "hello" string(5) "world"