2016-02-23 3 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

Немного хакерский.Вероятно, это сработает (я не уверен в «\» разделителе каталогов в Linux), но это не чистый код. Давайте предположим, что имя команды изменится на «cache: clear-now' или« console »изменится на' ezpublish '(на самом деле он называется таким образом в' ezpublish' cms), и он больше не будет работать –

+0

Затем они могут быть добавлены как параметры выше. Тем не менее, скорее всего, они не изменятся (хотя мы не должны зависеть от этого факта, существует довольно много проектов, в которых команда жестко закодирована в сценариях развертывания), и она должна работать только для Symfony. –

+0

Я изменил его, чтобы добавить в него больше команд. Пока он работает великолепно. –

4

Из-за того, как php работает - синхронно - это невозможно сделать в «классическом» способе, в котором вам нужно дождаться завершения команды, чтобы завершить и отправить ответ. Решение здесь состоит в том, чтобы включить шаблон worker. Вы можете найти полезную информацию here. В основном вам нужно добавить задачу «clear cache» в очередь и позволить другому процессу обрабатывать эту очередь, поэтому в вашем случае вызовите команду 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

Другая проблема заключается в том, что добавление слишком большого количества событий для запроса, ответа и завершения делает приложение медленным, я считаю. Я мог ошибаться, но по-прежнему не имеет смысла просить об этом по каждому запросу. –

Смежные вопросы