使用事件

3.4 版本
维护中的版本

Console组件中的Application类,令你能够可选地通过事件来打入到命令行程序的生命周期中。并非重复发明轮子,它使用了Symfony的EventDispatcher(事件派遣)组件来完成工作:

1
2
3
4
5
6
7
8
use Symfony\Component\Console\Application;
use Symfony\Component\EventDispatcher\EventDispatcher;
 
$dispatcher = new EventDispatcher();
 
$application = new Application();
$application->setDispatcher($dispatcher);
$application->run();

命令行事件,仅在主力命令(main command)执行时触发。由主命令调用的命令,将不触发任何事件。

ConsoleEvents::COMMAND事件 

主要目的:在命令运行之前做一些事(比如对将要执行的命令做日志),或者显示一些“即将被执行的事件”之相关内容。

就在任何命令被执行之前, ConsoleEvents::COMMAND 事件被派遣。监听器收到是一个 ConsoleCommandEvent 事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\ConsoleEvents;
 
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
    // get the input instance / 取得input实例
    $input = $event->getInput();
 
    // get the output instance / 取得output实例
    $output = $event->getOutput();
 
    // get the command to be executed / 取得将要执行的命令
    $command = $event->getCommand();
 
    // write something about the command / 写入和命令有关的内容
    $output->writeln(sprintf('Before running command <info>%s</info>', $command->getName()));
 
    // get the application / 获取application
    $application = $command->getApplication();
});

在监听中禁用命令 

使用 disableCommand() 方法,你可以在监听中禁用命令。程序将 不再 执行命令,而是会返回 113 (定义在 ConsoleCommandEvent::RETURN_CODE_DISABLED)。这个code是 reserved exit codes(保留退出码)中的一个,用于使控制台命令符合 C/C++ 标准:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\ConsoleEvents;
 
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
    // get the command to be executed / 取得将要执行的命令
    $command = $event->getCommand();
 
    // ... check if the command can be executed
    // ... 检查命令是否可以被执行
 
    // disable the command, this will result in the command being skipped
    // and code 113 being returned from the Application
    // 禁用命令,将导致命令被跳过,并从Application中返回113 code。
    $event->disableCommand();
 
    // it is possible to enable the command in a later listener
    // 也可以在后面的监听中开启命令
    if (!$event->commandShouldRun()) {
        $event->enableCommand();
    }
});

ConsoleEvents::EXCEPTION事件 

主要目的:在命令执行的过程中,处理“异常抛出”。

只要是在命令行中抛出异常,ConsoleEvents::EXCEPTION 事件就被派遣。监听器可以打包或改变此异常,或是在异常被程序抛出之前,做一些有用的事。

监听接收的是 ConsoleExceptionEvent 事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
use Symfony\Component\Console\Event\ConsoleExceptionEvent;
use Symfony\Component\Console\ConsoleEvents;
 
$dispatcher->addListener(ConsoleEvents::EXCEPTION, function (ConsoleExceptionEvent $event) {
    $output = $event->getOutput();
 
    $command = $event->getCommand();
 
    $output->writeln(sprintf('Oops, exception thrown while running command <info>%s</info>', $command->getName()));
 
    // get the current exit code (the exception code or the exit code set by a ConsoleEvents::TERMINATE event)
    // 获取当前的退出码(异常代码或是退出码的设置,是通过ConsoleEvents::TERMINATE事件来完成)
    $exitCode = $event->getExitCode();
 
    // change the exception to another one / 把异常改为另一个
    $event->setException(new \LogicException('Caught exception', $exitCode, $event->getException()));
});

ConsoleEvents::TERMINATE事件 

主要目的:在命令执行完毕后,执行一些清场的动作。

在命令被执行之后,ConsoleEvents::TERMINATE 事件被派遣。它可用于为“所有命令”做任何“需要被执行”的操作,或者用于清除你在 ConsoleEvents::COMMAND 监听中所初始化的东西(比如发送日志,关闭数据库连接,发送邮件,...)。监听也可能会改变退出码(exit code)。

监听接收的是 ConsoleTerminateEvent 事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
use Symfony\Component\Console\ConsoleEvents;
 
$dispatcher->addListener(ConsoleEvents::TERMINATE, function (ConsoleTerminateEvent $event) {
    // get the output / 获取output
    $output = $event->getOutput();
 
    // get the command that has been executed / 获取已被执行的命令
    $command = $event->getCommand();
 
    // display something / 显示内容
    $output->writeln(sprintf('After running command <info>%s</info>', $command->getName()));
 
    // change the exit code / 改变退出码
    $event->setExitCode(128);
});

本事件也会在“有异常被命令抛出”的时候派遣。它是在 ConsoleEvents::EXCEPTION 事件之后被派遣。本例中的退出码就是异常代码(exception code)。

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)