代码之家  ›  专栏  ›  技术社区  ›  George Irimiciuc

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

  •  3
  • George Irimiciuc  · 技术社区  · 10 年前

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

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

    在我的控制器中,我有一个选择命令的窗体,当选择了缓存清除命令时,它会运行:

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

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

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

    4 回复  |  直到 10 年前
        1
  •  4
  •   Community Mohan Dere    9 年前

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

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

    Using in symfony

    RabbitMQBundle

    Let RabbitMQ Do The Work In Your Symfony2 Application

        2
  •  2
  •   Anna Adamchuk    10 年前

    要在响应后运行命令,必须在 内核终止 事件此事件的目的是在响应已送达客户端后执行任务。

    // 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

        3
  •  1
  •   Community Mohan Dere    9 年前

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

    我在这里给出的一些代码示例是我对类似问题的老答案: Asynchronously calling a Command in Symfony2

        4
  •  0
  •   George Irimiciuc    10 年前

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

    /**
     * @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);
    
        }
    
    
    }