Search code examples
phpsymfonysymfony-console

Symfony run command from controller on the server


I want to clear the cache from the controller. I have defined the command as a service and call it.

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

In my controller I have a form to choose a command, and when the cache-clearing command is chosen it runs:

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

This however runs for a while, since it also warms up the cache (I actually want it to also warm it up). It also times out so I need to set_time_limit it, too.

Is there a way to return a response in the browser and let the command run and finish on the server? I don't want the client to keep waiting for it to finish.


Solution

  • I found a way to do it. This will immediately return a response and have the command run in background. Not sure how much of a bad practice it is.

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