Symfony - 运行 kernel.terminate 上的控制台命令
Symfony - run console command on kernel.terminate
我已将 swiftmailer 配置为使用文件类型假脱机电子邮件。这是我的 swiftmailer 配置
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool:
type: file
path: "%kernel.root_dir%/../var/spool"
当我发送任何电子邮件时,它完美地假脱机。我 运行 按照命令发送电子邮件。
bin/console swiftmailer:spool:send --env=dev
根据 Symfony documentation
the console command should be triggered by a cron job or scheduled task and run at a regular interval.
我的问题是,我无法使用 crontab,因为 cron 可以配置为至少 1 分钟的间隔,而我无法承受。我想在响应发送回浏览器后立即执行后台进程,从而将假脱机的执行降至最低限度。
我试图通过创建一个事件侦听器 class 并侦听 kernel.terminate
来解决这个问题,并使用 shell_exec
或 exec
函数执行命令,这里是参考代码
app.kernel.terminate.listener:
arguments: ["@kernel"]
class: AppBundle\EventListener\KernelTerminateListener
tags:
- { name: kernel.event_listener, event: kernel.terminate }
这是我的 EventListener class
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Cocur\BackgroundProcess\BackgroundProcess;
class KernelTerminateListener
{
protected $kernel;
protected $console;
public function __construct($kernel)
{
$this->kernel = $kernel;
$this->console = $this->kernel->getRootDir().'/../bin/console ';
}
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->console.'swiftmailer:spool:send --env='.$this->kernel->getEnvironment();
shell_exec($command);
}
}
我在这里尝试的是 运行 bin/console swiftmailer:spool:send --env=dev
在 kernel.terminate
事件上,不幸的是这不起作用,感谢任何关于如何解决这个问题的提示。
谢谢。
可能是 PHP 的问题,我正在使用 MAMP,OSX 带有 pre-installed 和 PHP,基本上,我有两个 php安装的版本,出于某种原因,当我给出正确的 PHP 路径时,它起作用了,这是我更新的监听器 class,我将其重命名为 MailerSpoolListener
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Cocur\BackgroundProcess\BackgroundProcess;
class MailerSpoolListener
{
protected $kernel;
protected $php;
protected $console;
protected $env;
protected $command;
protected $muteOutput;
public function __construct($kernel)
{
$this->kernel = $kernel;
$this->php = PHP_BINDIR.'/php';
$this->command = 'swiftmailer:spool:send';
$this->console = $this->kernel->getRootDir().'/../bin/console';
$this->env = $this->kernel->getEnvironment();
$this->muteOutput = '> /dev/null 2>/dev/null &';
}
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->php.' '.$this->console.' '.$this->command.' --env='.$this->env.' '.$this->muteOutput;
$process = shell_exec($command);
}
}
请使用 swift 邮件程序的内存假脱机类型,它完全符合您的要求
When you use spooling to store the emails to memory, they will get sent right before the kernel terminates. This means the email only gets sent if the whole request got executed without any unhandled exception or any errors. To configure swiftmailer with the memory option, use the following configuration:
而不是使用 shel_exec 使用进程组件,这将创建一个新进程,命令将在发送响应后执行。
shel_exec 或 exec 将在同一进程下执行,这会强制内核等待完成请求(因为一旦父进程被杀死,子进程也会终止)。进程组件会创建一个新的进程,在该进程下执行命令。
use Symfony\Component\Process\Process;
....
....
....
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->console.'swiftmailer:spool:send --env=.'$this->kernel->getEnvironment().'> output.log 2> out.log &';
$process = new Process($command);
$process->run();
}
我已将 swiftmailer 配置为使用文件类型假脱机电子邮件。这是我的 swiftmailer 配置
swiftmailer:
transport: "%mailer_transport%"
host: "%mailer_host%"
username: "%mailer_user%"
password: "%mailer_password%"
spool:
type: file
path: "%kernel.root_dir%/../var/spool"
当我发送任何电子邮件时,它完美地假脱机。我 运行 按照命令发送电子邮件。
bin/console swiftmailer:spool:send --env=dev
根据 Symfony documentation
the console command should be triggered by a cron job or scheduled task and run at a regular interval.
我的问题是,我无法使用 crontab,因为 cron 可以配置为至少 1 分钟的间隔,而我无法承受。我想在响应发送回浏览器后立即执行后台进程,从而将假脱机的执行降至最低限度。
我试图通过创建一个事件侦听器 class 并侦听 kernel.terminate
来解决这个问题,并使用 shell_exec
或 exec
函数执行命令,这里是参考代码
app.kernel.terminate.listener:
arguments: ["@kernel"]
class: AppBundle\EventListener\KernelTerminateListener
tags:
- { name: kernel.event_listener, event: kernel.terminate }
这是我的 EventListener class
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Cocur\BackgroundProcess\BackgroundProcess;
class KernelTerminateListener
{
protected $kernel;
protected $console;
public function __construct($kernel)
{
$this->kernel = $kernel;
$this->console = $this->kernel->getRootDir().'/../bin/console ';
}
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->console.'swiftmailer:spool:send --env='.$this->kernel->getEnvironment();
shell_exec($command);
}
}
我在这里尝试的是 运行 bin/console swiftmailer:spool:send --env=dev
在 kernel.terminate
事件上,不幸的是这不起作用,感谢任何关于如何解决这个问题的提示。
谢谢。
可能是 PHP 的问题,我正在使用 MAMP,OSX 带有 pre-installed 和 PHP,基本上,我有两个 php安装的版本,出于某种原因,当我给出正确的 PHP 路径时,它起作用了,这是我更新的监听器 class,我将其重命名为 MailerSpoolListener
<?php
namespace AppBundle\EventListener;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
use Cocur\BackgroundProcess\BackgroundProcess;
class MailerSpoolListener
{
protected $kernel;
protected $php;
protected $console;
protected $env;
protected $command;
protected $muteOutput;
public function __construct($kernel)
{
$this->kernel = $kernel;
$this->php = PHP_BINDIR.'/php';
$this->command = 'swiftmailer:spool:send';
$this->console = $this->kernel->getRootDir().'/../bin/console';
$this->env = $this->kernel->getEnvironment();
$this->muteOutput = '> /dev/null 2>/dev/null &';
}
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->php.' '.$this->console.' '.$this->command.' --env='.$this->env.' '.$this->muteOutput;
$process = shell_exec($command);
}
}
请使用 swift 邮件程序的内存假脱机类型,它完全符合您的要求
When you use spooling to store the emails to memory, they will get sent right before the kernel terminates. This means the email only gets sent if the whole request got executed without any unhandled exception or any errors. To configure swiftmailer with the memory option, use the following configuration:
而不是使用 shel_exec 使用进程组件,这将创建一个新进程,命令将在发送响应后执行。 shel_exec 或 exec 将在同一进程下执行,这会强制内核等待完成请求(因为一旦父进程被杀死,子进程也会终止)。进程组件会创建一个新的进程,在该进程下执行命令。
use Symfony\Component\Process\Process;
....
....
....
public function onKernelTerminate(PostResponseEvent $event)
{
$command = $this->console.'swiftmailer:spool:send --env=.'$this->kernel->getEnvironment().'> output.log 2> out.log &';
$process = new Process($command);
$process->run();
}