2016-02-23 124 views
3

我想清除控制器中的緩存。我已將該命令定義爲服務並調用它。Symfony從服務器上的控制器運行命令

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

有沒有辦法在瀏覽器中返回響應並讓命令在服務器上運行並完成?我不希望客戶繼續等待它完成。

回答

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); 

    } 


} 
+0

它有點ha。。它可能會工作(我不知道在Linux中的「\」目錄分隔符),但它不是乾淨的代碼 - 讓我們設想命令的名稱將改變爲'緩存:clear-now'或'console'將更改爲'ezpublish '(實際上它在'ezpublish' cms中被稱爲這種方式)並且不再起作用 –

+0

然後可以將它們作爲上面的參數添加。儘管如此,它們很可能不會改變(雖然我們不應該依賴這個事實,但是有相當多的項目在部署腳本的某個地方使用了硬編碼的命令),並且它只能用於Symfony。 –

+0

我改變了它,所以更多的命令可以添加到它。到目前爲止,它的工作非常出色。 –

4

由於php的工作原理 - 同步 - 無法以「傳統」方式執行,您需要等待命令完成才能終止併發送響應。這裏的解決方案是納入worker模式。你可以找到一些有用的信息here。基本上你需要添加「清除緩存」任務到隊列,讓其他進程處理這個隊列,所以在你的情況下調用clear cache命令。

在這種情況下,在symfony中一種常用的解決方案是使用RabbitMQ,有一個關於它的大量資源:

Using in symfony

RabbitMQBundle

Let RabbitMQ Do The Work In Your Symfony2 Application

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

+0

的kernel.terminate的問題在於,它會在每個請求中偵聽,而當我只需要在一個地方時它沒有意義。 –

+0

另一個問題是,爲請求,響應,終止添加太多的事件會讓應用程序變慢,我相信。我可能是錯的,但在每次請求時都要求這樣做是沒有意義的。 –