Symfony 控制台:事件未触发
Symfony Console: Event not Firing
在 these instructions 之后,我已经使用以下命令安装了 Symfony 3.4。
composer.phar create-project symfony/framework-standard-edition my_project_name_3_4
然后,在 these other instructions 之后,我向股票控制台应用程序添加了一个事件调度程序,以及一个事件侦听器
#File: my_project_name_3_4/bin/console
/* ... other code ... */
$application = new Application($kernel);
//START: my new code
//create dispatcher and add to application
use Symfony\Component\EventDispatcher\EventDispatcher;
$dispatcher = new EventDispatcher();
$application->setDispatcher($dispatcher);
//add my event to dispatcher
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\ConsoleEvents;
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
exit("\n\nHey, Symfony called my event! Let's crash this party! \n\n");
});
//END: my new code
$application->run($input);
然而,当我 运行 一个 Symfony 控制台命令时,
php bin/console help
我的事件没有触发。我希望上面的代码在 Symfony 调用我的 ConsoleEvents::COMMAND
监听器时停止。
我做了一些调试,似乎调用 $application->run
从调度程序中删除了 我的事件?!在我深入进行适当数量的调试之前,我想检查一下是否有明显的错误,是否有已知的科学来解决这个问题。是否有其他方法可以将事件添加到标准的 Symfony 控制台应用程序?
我想我应该更仔细地阅读这个问题。一路走到尽头。我有点专注于如何修改 bin/console.
在任何情况下(双关语),您都可以像 add any event listener 一样添加命令侦听器。
namespace AppBundle;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MySubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// return the subscribed events, their methods and priorities
return array(
ConsoleEvents::COMMAND => array(
array('onCommand', 0),
)
);
}
public function onCommand(ConsoleCommandEvent $event)
{
echo "onCommand\n";
}
}
并且由于默认的自动装配和自动配置,您甚至不必向 services.yml 添加任何内容。它只是工作。
===============================
原答案
我认为您可能将控制台组件与控制台框架文档混为一谈。
首先通过编辑框架安装的 bin/console 文件来回答您的问题:
# bin/console
use Symfony\Bundle\FrameworkBundle\Console\Application as FrameworkApplication;
$kernel = new AppKernel($env, $debug);
$kernel->boot();
$application = new FrameworkApplication($kernel);
$dispatcher = $kernel->getContainer()->get('event_dispatcher');
$dispatcher->addListener(\Symfony\Component\Console\ConsoleEvents::COMMAND,
function (\Symfony\Component\Console\Event\ConsoleCommandEvent $event) {
exit("\n\nHey, Symfony called my event! Let's crash this party! \n\n");
});
$application->run($input);
它是基于使用框架应用程序 class 的完全有效的代码。
但是,您问题中的第二个 link 指向基于组件应用程序 class 的控制台组件文档。
use Symfony\Component\Console\Application as ComponentApplication;
ComponentApplication class 不了解内核或容器。它几乎是独立的,并提供了一种通过 ComponentApplication::setDispatcher 注入事件调度程序的方法。如果您使用 ComponentApplication class 尽管您必须注册自己的命令,但您在问题中尝试的代码会工作得很好。
FrameworkApplication从内核中拉取容器,然后从中拉取事件分发器并传递给setDispatcher。它还使用内核来注册命令。 class 中没有任何内容实际上依赖于未引导的内核。内核 class 本身会防止多次启动。
因此在调用 FrameworkApplication::run() 之前启动内核并访问容器是可以的。
我想如果你真的想以 "non-dirty" 的方式做到这一点,那么只需扩展应用程序 class 并在 doRun 方法中添加你的侦听器。
在 these instructions 之后,我已经使用以下命令安装了 Symfony 3.4。
composer.phar create-project symfony/framework-standard-edition my_project_name_3_4
然后,在 these other instructions 之后,我向股票控制台应用程序添加了一个事件调度程序,以及一个事件侦听器
#File: my_project_name_3_4/bin/console
/* ... other code ... */
$application = new Application($kernel);
//START: my new code
//create dispatcher and add to application
use Symfony\Component\EventDispatcher\EventDispatcher;
$dispatcher = new EventDispatcher();
$application->setDispatcher($dispatcher);
//add my event to dispatcher
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Console\ConsoleEvents;
$dispatcher->addListener(ConsoleEvents::COMMAND, function (ConsoleCommandEvent $event) {
exit("\n\nHey, Symfony called my event! Let's crash this party! \n\n");
});
//END: my new code
$application->run($input);
然而,当我 运行 一个 Symfony 控制台命令时,
php bin/console help
我的事件没有触发。我希望上面的代码在 Symfony 调用我的 ConsoleEvents::COMMAND
监听器时停止。
我做了一些调试,似乎调用 $application->run
从调度程序中删除了 我的事件?!在我深入进行适当数量的调试之前,我想检查一下是否有明显的错误,是否有已知的科学来解决这个问题。是否有其他方法可以将事件添加到标准的 Symfony 控制台应用程序?
我想我应该更仔细地阅读这个问题。一路走到尽头。我有点专注于如何修改 bin/console.
在任何情况下(双关语),您都可以像 add any event listener 一样添加命令侦听器。
namespace AppBundle;
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MySubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents()
{
// return the subscribed events, their methods and priorities
return array(
ConsoleEvents::COMMAND => array(
array('onCommand', 0),
)
);
}
public function onCommand(ConsoleCommandEvent $event)
{
echo "onCommand\n";
}
}
并且由于默认的自动装配和自动配置,您甚至不必向 services.yml 添加任何内容。它只是工作。
===============================
原答案
我认为您可能将控制台组件与控制台框架文档混为一谈。
首先通过编辑框架安装的 bin/console 文件来回答您的问题:
# bin/console
use Symfony\Bundle\FrameworkBundle\Console\Application as FrameworkApplication;
$kernel = new AppKernel($env, $debug);
$kernel->boot();
$application = new FrameworkApplication($kernel);
$dispatcher = $kernel->getContainer()->get('event_dispatcher');
$dispatcher->addListener(\Symfony\Component\Console\ConsoleEvents::COMMAND,
function (\Symfony\Component\Console\Event\ConsoleCommandEvent $event) {
exit("\n\nHey, Symfony called my event! Let's crash this party! \n\n");
});
$application->run($input);
它是基于使用框架应用程序 class 的完全有效的代码。
但是,您问题中的第二个 link 指向基于组件应用程序 class 的控制台组件文档。
use Symfony\Component\Console\Application as ComponentApplication;
ComponentApplication class 不了解内核或容器。它几乎是独立的,并提供了一种通过 ComponentApplication::setDispatcher 注入事件调度程序的方法。如果您使用 ComponentApplication class 尽管您必须注册自己的命令,但您在问题中尝试的代码会工作得很好。
FrameworkApplication从内核中拉取容器,然后从中拉取事件分发器并传递给setDispatcher。它还使用内核来注册命令。 class 中没有任何内容实际上依赖于未引导的内核。内核 class 本身会防止多次启动。
因此在调用 FrameworkApplication::run() 之前启动内核并访问容器是可以的。
我想如果你真的想以 "non-dirty" 的方式做到这一点,那么只需扩展应用程序 class 并在 doRun 方法中添加你的侦听器。