Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Symfony从服务器上的控制器运行命令_Php_Symfony_Symfony Console - Fatal编程技术网

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

Php Symfony从服务器上的控制器运行命令,php,symfony,symfony-console,Php,Symfony,Symfony Console,我想从控制器中清除缓存。我已经将命令定义为服务并调用它 clear_cache_command_service: class: Symfony\Bundle\FrameworkBundle\Command\CacheClearCommand calls: - [setContainer, ["@service_container"] ] 在我的控制器中,我有一个表单来选择命令,当选择缓存清除命令时,它将运行: $clearCacheCommand = $t

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

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());
不过,这会运行一段时间,因为它也会使缓存升温(实际上我希望它也会升温)。它也会超时,所以我也需要设置时间限制


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

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

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


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

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

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


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

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

    }


}

作为前面提到的RabbitMQ的替代方案,您可以查看JMSJobBundle


我在这里给出了一些代码示例,我以前对类似问题的回答是:

kernel.terminate的问题是它会侦听每个请求,当我只在一个地方需要它时,它就没有意义了。另一个问题是为request、response、terminate添加太多事件,我相信这会使应用程序运行缓慢。我可能错了,但每次提出要求都要这个还是没有意义的。这有点老套。它可能会工作(我不确定linux中的“\”目录分隔符),但它不是干净的代码-让我们想象一下,命令名称将更改为
cache:clear now
,或者
console
将更改为
ezpublish
(事实上,它在
ezpublish
cms中以这种方式命名)它将不再工作,然后这些可以添加为上述参数。即便如此,它们也很可能不会改变(尽管我们不应该依赖这一事实,有相当多的项目在部署脚本中的某个地方硬编码了该命令),而且它应该只对Symfony有效。我已经对其进行了更改,以便可以向其添加更多命令。到目前为止,它的工作非常出色。