3

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

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

In my controller I have a form to choose a command, and when the cache-clearing command is chosen it runs:

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

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

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

4

4 回答 4

4

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

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

在 symfony 中使用

RabbitMQBundle

让 RabbitMQ 在您的 Symfony2 应用程序中完成工作

于 2016-02-23T08:26:55.073 回答
2

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

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

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

监听器示例

kernel.terminate 事件文档

于 2016-02-23T08:28:36.867 回答
1

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

我在此给出的一些代码示例是我对类似问题的旧答案:Asynchronously call a Command in Symfony2

于 2016-02-23T13:21:21.230 回答
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);

    }


}
于 2016-02-23T08:32:04.947 回答