Como posso executar o comando symfony 2 run a partir do controller

Eu estou querendo saber como posso executar o comando Symfony 2 a partir da consulta do navegador ou do controlador.

É porque eu não tenho nenhuma possibilidade de hospedagem para executá-lo e todos os trabalhos cron são definidos pelo administrador.

Eu nem sequer tenho ativado a function exec() , então quando eu quiser testá-lo, eu devo copiar todo o conteúdo do comando para algum controlador de teste e esta não é a melhor solução.

Veja a documentação oficial sobre este problema para versões mais recentes do Symfony


Você não precisa de serviços para execução de comando do controlador e, eu acho, é melhor chamar o comando via método de run e não via input de seqüência de caracteres do console, no entanto documentos oficiais sugerem que você chame o comando via alias. Além disso, veja esta resposta . Testado no Symfony 2.1-2.6.

Sua class de comando deve estender o ContainerAwareCommand

 // Your command use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; class MyCommand extends ContainerAwareCommand { // … } // Your controller use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; class SomeController extends Controller { // … public function myAction() { $command = new MyCommand(); $command->setContainer($this->container); $input = new ArrayInput(array('some-param' => 10, '--some-option' => true)); $output = new NullOutput(); $resultCode = $command->run($input, $output); } } 

Na maioria dos casos, você não precisa de BufferedOutput ( da resposta de Jbm ) e é suficiente verificar se $resultCode is 0 , caso contrário, houve um erro.

Registre seu comando como um serviço e não se esqueça de chamar setContainer

 MyCommandService: class: MyBundle\Command\MyCommand calls: - [setContainer, ["@service_container"] ] 

No seu controlador, você só precisa obter esse serviço e chamar o método execute com os argumentos de direitos

Configure a input com o método setArgument :

 $input = new Symfony\Component\Console\Input\ArgvInput(); $input->setArgument('arg1', 'value'); $output = new Symfony\Component\Console\Output\ConsoleOutput(); 

Chame o método de run do comando:

 $command = $this->get('MyCommandService'); $command->run($input, $ouput); 

No meu ambiente (Symony 2.1) eu tive que fazer algumas modificações na solução @Reuven para fazê-lo funcionar. Aqui estão eles:

Definição de serviço – sem alterações.

No controlador:

 use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; ... public function myAction() { $command = $this->get('MyCommandService'); $input = new ArgvInput(array('arg1'=> 'value')); $output = new ConsoleOutput(); $command->run($input, $output); } 

Aqui está uma alternativa que permite executar comandos como strings da mesma maneira que você faria no console (não há necessidade de definir serviços com este).

Você pode verificar o controlador deste pacote para ver como ele é feito com todos os detalhes. Aqui vou resumir isso omitindo certos detalhes (como manipular o ambiente, então aqui todos os comandos serão executados no mesmo ambiente em que são invocados).

Se você quiser apenas executar comandos a partir do navegador, pode usar esse pacote como está, mas se quiser executar comandos a partir de um controlador arbitrário, veja como fazer isso:

Em seu controlador, defina uma function como esta:

 use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Input\StringInput; private function execute($command) { $app = new Application($this->get('kernel')); $app->setAutoExit(false); $input = new StringInput($command); $output = new BufferedOutput(); $error = $app->run($input, $output); if($error != 0) $msg = "Error: $error"; else $msg = $output->getBuffer(); return $msg; } 

Então você pode invocá-lo de uma ação como esta:

 public function dumpassetsAction() { $output = $this->execute('assetic:dump'); return new Response($output); } 

Além disso, você precisa definir uma class para atuar como buffer de saída, porque não existe nenhuma fornecida pelo framework:

 use Symfony\Component\Console\Output\Output; class BufferedOutput extends Output { public function doWrite($message, $newline) { $this->buffer .= $message. ($newline? PHP_EOL: ''); } public function getBuffer() { return $this->buffer; } } 

mesmo que @malloc mas

 use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; ... public function myAction() { $command = $this->get('MyCommandService'); // $input[0] : command name // $input[1] : argument1 $input = new ArgvInput(array('my:command', 'arg1')); $output = new ConsoleOutput(); $command->run($input, $output); } 

Você pode simplesmente criar uma instância do seu comando e executá-la:

 /** * @Route("/run-command") */ public function someAction() { // Running the command $command = new YourCommand(); $command->setContainer($this->container); $input = new ArrayInput(['--your_argument' => true]); $output = new ConsoleOutput(); $command->run($input, $output); return new Response(); } 

Se você tiver que passar argumentos (e / ou opções), então em v2.0.12 (e pode ser verdadeiro para versões posteriores), você precisa especificar InputDefinition primeiro antes de instanciar um object de input.

 use // you will need the following Symfony\Component\Console\Input\InputOption, Symfony\Component\Console\Input\InputArgument, Symfony\Component\Console\Input\InputDefinition, Symfony\Component\Console\Input\ArgvInput, Symfony\Component\Console\Output\NullOutput; // tell symfony what to expect in the input $inputDefinition = new InputDefinition(array( new InputArgument('myArg1', InputArgument::REQUIRED), new InputArgument('myArg2', InputArgument::REQUIRED), new InputOption('debug', '0', InputOption::VALUE_OPTIONAL), )); // then pass the values for arguments to constructor, however make sure // first param is dummy value (there is an array_shift() in ArgvInput's constructor) $input = new ArgvInput( array( 'dummySoInputValidates' => 'dummy', 'myArg2' => 'myValue1', 'myArg2' => 'myValue2'), $inputDefinition); $output = new NullOutput(); 

Como uma nota lateral, se você estiver usando se você estiver usando getContainer () em seu comando, então a seguinte function pode ser útil para o seu command.php:

 /** * Inject a dependency injection container, this is used when using the * command as a service * */ function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface $container = null) { $this->container = $container; } /** * Since we are using command as a service, getContainer() is not available * hence we need to pass the container (via services.yml) and use this function to switch * between conatiners.. * */ public function getcontainer() { if (is_object($this->container)) return $this->container; return parent::getcontainer(); } 

Você pode usar este pacote para executar comandos do Symfony2 a partir do controlador (solicitação http) e passar opções / parâmetros na URL.

https://github.com/mrafalko/CommandRunnerBundle

Se você executar um comando que precisa da opção env como assetic:dump

 $stdout->writeln(sprintf('Dumping all %s assets.', $input->getOption('env'))); 

Você tem que criar um Symfony\Component\Console\Application e definir a definição da seguinte forma:

 use Symfony\Component\Console\Application; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputDefinition; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\NullOuput; // Create and run the command of assetic $app = new Application(); $app->setDefinition(new InputDefinition([ new InputOption('env', '', InputOption::VALUE_OPTIONAL, '', 'prod') ])); $app->add(new DumpCommand()); /** @var DumpCommand $command */ $command = $app->find('assetic:dump'); $command->setContainer($this->container); $input = new ArgvInput([ 'command' => 'assetic:dump', 'write_to' => $this->assetsDir ]); $output = new NullOutput(); $command->run($input, $output); 

Você não pode definir a opção env para o comando porque não está em sua definição.

Intereting Posts