Symfony从服务器上的控制器运行命令

时间:2016-02-23 07:52:47

标签: php symfony symfony-console

我想从控制器中清除缓存。我已将该命令定义为服务并调用它。

clear_cache_command_service:
    class: Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand
    calls:
       - [setContainer, ["@service_container"] ]

在我的控制器中,我有一个表单来选择一个命令,当选择了cache-clearing命令时,它会运行:

    $clearCacheCommand = $this->container->get('clear_cache_command_service');
    $clearCacheCommand->run(new ArrayInput(array()), new ConsoleOutput());

然而这会运行一段时间,因为它也会使缓存变暖(我实际上也希望它也能加热它)。它也超时,所以我也需要set_time_limit它。

有没有办法在浏览器中返回响应并让命令在服务器上运行并完成?我不希望客户端等待它完成。

4 个答案:

答案 0 :(得分:4)

由于worker如何工作 - 同步 - 不可能以“经典”的方式进行,您需要等待命令完成终止并发送响应。这里的解决方案是合并clear cache模式。您可以找到一些有用的信息here。基本上你需要将“clear cache”任务添加到队列中,让其他进程处理这个队列,所以在你的情况下调用counter命令。

在这种情况下,symfony中使用的常见解决方案是使用RabbitMQ,有很多相关资源:

Using in symfony

RabbitMQBundle

Let RabbitMQ Do The Work In Your Symfony2 Application

答案 1 :(得分:2)

要在响应后运行命令,必须在 kernel.terminate 事件上使用侦听器。此事件的目的是在响应已经提供给客户端后执行任务。

// send the headers and echo the content
$response->send();

// triggers the kernel.terminate event
$kernel->terminate($request, $response);

Listener example

The kernel.terminate Event documentation

答案 2 :(得分:1)

作为已经提及的RabbitMQ的替代方案,您可以查看JMSJobBundle http://jmsyst.com/bundles/JMSJobQueueBundle/master/installation

我在这个问题上给出了一些代码示例:Asynchronously calling a Command in Symfony2

答案 3 :(得分:0)

我找到了办法。这将立即返回响应并使命令在后台运行。不确定这是多么糟糕的做法。

/**
 * @Service("background_command_runner")
 */
class BackgroundCommandRunner
{
    private $kernelDir;


    /**
     * @InjectParams({
     *     "kernelDir" = @Inject("%kernel.root_dir%")
     * })
     */
    public function __construct($kernelDir)
    {
        $this->kernelDir = $kernelDir;
    }

    public function run($cmd)
    {
        $path = $this->kernelDir . '\console ';

        $fullCmd = "php " . $path . $cmd;

        if (substr(php_uname(), 0, 7) == "Windows") {
            pclose(popen("start /B " . $fullCmd, "r"));
        } else {
            exec($fullCmd . " >> logs/theme.log &");
        }
    }

    public function clearCache($env = "dev", $warm = true)
    {

        $toWarm = $warm ? "" : " --no-warmup";

        $cmd = "cache:clear " . "--env=" . $env . $toWarm;

        $this->run($cmd);

    }


}