Я хочу очистить кеш от контроллера. Я определил команду как службу и вызываю ее.
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
это тоже.
Есть ли способ вернуть ответ в браузере и позволить команде выполнить и завершить работу на сервере? Я не хочу, чтобы клиент продолжал ждать его окончания.
Из-за того, как php
работает — синхронно — это невозможно сделать «классическим» способом, в котором вам нужно ждать, пока команда завершится, чтобы завершить и отправить ответ. Решение здесь состоит в том, чтобы включить worker
шаблон. Вы можете найти полезную информацию Вот. По сути, вам нужно добавить задачу «очистить кеш» в очередь и позволить другому процессу обрабатывать эту очередь, так что в вашем случае вызовите clear cache
команда.
Распространенным решением, используемым в Symfony в таких случаях, является использование RabbitMQ, Есть много ресурсов об этом:
Позвольте RabbitMQ сделать работу в вашем приложении Symfony2
Для запуска команды после ответа вы должны использовать слушатель на kernel.terminate событие. Цель этого события — выполнить задачи после того, как ответ уже был передан клиенту.
// send the headers and echo the content
$response->send();
// triggers the kernel.terminate event
$kernel->terminate($request, $response);
В качестве альтернативы RabbitMQ, о которой уже упоминалось, вы можете взглянуть на JMSJobBundle
http://jmsyst.com/bundles/JMSJobQueueBundle/master/installation
Пример кода, который я дал на этот мой старый ответ на похожий вопрос: Асинхронный вызов команды в Symfony2
Я нашел способ сделать это. Это немедленно вернет ответ и запустит команду в фоновом режиме. Не уверен, насколько это плохая практика.
/**
* @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);
}}