本文概述
有很多原因导致你应该在控制器中执行控制台命令, 而不是再次重写控制器中的所有逻辑。实际上, 如果需要在两个不同的区域中使用相同的代码, 则可能需要隔离该逻辑并将其公开在服务中。然后, 在控制台中, 就像在控制台命令中一样, 你将能够访问容器, 需要服务并执行它。但是, 如果我们谈论的是第三方捆绑软件的逻辑该怎么办?你不会从捆绑包中复制命令代码, 然后将其粘贴到控制器中, 该死。相反, 建议仅从控制器执行console命令。
在本文中, 你将学习如何直接从控制器中使用控制台命令。
继续之前
在这种情况下, 我们将执行以下命令(php bin /控制台应用程序:print-lines –firstline =” Hello” –secondline =” World”):
<?php
// myapplication/src/AppBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace AppBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
// Add the required classes
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
class TestCommand extends Command
{
protected function configure()
{
$this
// the name of the command (the part after "bin/console")
->setName('app:print-lines')
// the short description shown while running "php bin/console list"
->setHelp("This command allows you to print some text in the console")
// the full command description shown when running the command with
->setDescription('Prints some text into the console with given parameters.')
// Set options
->setDefinition(
new InputDefinition(array(
new InputOption('firstline', 'a', InputOption::VALUE_REQUIRED, "The first line to be printed", "Default First Line Value"), new InputOption('secondline', 'b', InputOption::VALUE_OPTIONAL, "The second line to be printed", "Default First Line Value"), ))
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
// outputs multiple lines to the console (adding "\n" at the end of each line)
$output->writeln([
'My Third Symfony command', // A line
'============', // Another line
'', // Empty line
]);
$firstLine = $input->getOption('firstline');
$secondline = $input->getOption('secondline');
$output->writeln("First line value : ".$firstLine);
if($secondline){
$output->writeln("Second line value : ".$secondline);
}
// Instead of retrieve line per line every option, you can get an array of all the providen options :
//$output->writeln(json_encode($input->getOptions()));
}
}
如果要学习如何为Symfony创建自定义控制台命令, 请阅读本文。否则, 如果你已经拥有一个, 则继续执行。
实现
你可以从控制器执行任何控制台命令, 只要它不是动态的(需要在其中进行交互的命令)或与项目中的文件混淆的命令(例如clear cache命令)即可。从命令的执行中, 你可以决定是否检索输入:
带输出
要在控制器内执行命令, 请使用以下代码:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
// Import the required classed
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function indexAction()
{
$kernel = $this->get('kernel');
$application = new Application($kernel);
$application->setAutoExit(false);
$input = new ArrayInput(array(
'command' => 'app:print-lines', '--firstline' => "Hello", '--secondline' => "World"
));
$output = new BufferedOutput();
$application->run($input, $output);
// return the output
$content = $output->fetch();
// Send the output of the console command as response
return new Response($content);
}
}
先前的控制器将在浏览器中作为响应返回”我的第三Symfony命令=============第一行值:Hello第二行值:World”。
无输出
如果你不关心命令生成的输出, 因为它不重要或生成了自定义日志, 则可以忽略BufferedOutput。在这种情况下, 由于无法知道命令是否已成功执行, 因此将使用以下自定义命令(它将在项目的/ web文件夹中创建一个文本文件, 以确保该命令已通过控制台执行可以使用php bin /控制台应用程序执行:create-file-web –filename =” test” –extension =” txt”):
<?php
// myapplication/src/AppBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace AppBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
// Add the required classes
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;
// Add the Container
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
class TestCommand extends ContainerAwareCommand
{
protected function configure()
{
$this
// the name of the command (the part after "bin/console")
->setName('app:create-file-web')
// the short description shown while running "php bin/console list"
->setHelp("This command creates a file")
// the full command description shown when running the command with
->setDescription('Creates a file with a custom filename')
// Set options
->setDefinition(
new InputDefinition(array(
new InputOption('filename', 'a', InputOption::VALUE_REQUIRED, "The filename", "mytextfile"), new InputOption('extension', 'b', InputOption::VALUE_OPTIONAL, "The extension of the file", "txt"), ))
)
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$filename = $input->getOption('filename');
$extension = $input->getOption('extension');
$webFolder = $this->getContainer()->get('kernel')->getRootDir() . '/../web/';
// Create the file with custom name and extension in the /web path
$myfile = fopen($webFolder. "$filename.$extension", "w");
$txt = "Command succesfully executed";
fwrite($myfile, $txt);
fclose($myfile);
}
}
可以使用以下代码从控制器执行此操作(无需检索输出):
注意
完全不使用BufferedOutput, 需要将其替换为NullOutput
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;
// Import the required classed
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
class DefaultController extends Controller
{
/**
* @Route("/", name="homepage")
*/
public function indexAction()
{
$kernel = $this->get('kernel');
$application = new Application($kernel);
$application->setAutoExit(false);
$input = new ArrayInput(array(
'command' => 'app:create-file-web', '--filename' => "test", '--extension' => "txt"
));
// Use the NullOutput class instead of BufferedOutput.
$output = new NullOutput();
$application->run($input, $output);
return new Response("Command succesfully executed from the controller");
}
}
控制器应返回响应”从控制器成功执行命令”, 即使未正确执行也是如此。要检查它是否真正执行, 请验证文件是否在项目的/ web路径中创建。如果你需要有关控制台组件的更多信息, 请在此处阅读文档。
编码愉快!
评论前必须登录!
注册