如何在Symfony 3中创建和执行自定义控制台命令

本文概述

  • 你的第一个命令
  • 处理和设置命令参数(输入)
  • 处理和设置命令选项(输入参数)
  • 集装箱服务
  • 总结
Symfony框架通过bin / console脚本提供了许多命令(例如, 众所周知的bin / console cache:clear命令)。这些命令是使用控制台组件创建的。
你还可以使用它使用相同的控制台组件轻松地创建自己的命令, 在本文中, 你将学习如何使用参数和参数创建第一个自定义控制台命令。
你的第一个命令 为了了解所需的结构以及命令的工作方式, 我们将实现你的第一个命令, 该命令基本上会在控制台中打印一些文本。命令是在必须在包的命令命名空间中创建的类中定义的(例如sandboxBundle \ Command), 并且它们的名称必须以Command后缀结尾。
首先, 找到你要在其中创建命令的包(在这种情况下, 我们的包为sandboxBundle), 并在其上创建一个名为Command的文件夹。在Command文件夹中, 创建一个名为TestCommand.php的新类。
你的捆绑包结构应类似于:
如何在Symfony 3中创建和执行自定义控制台命令

文章图片
最后, 将以下代码添加到先前创建的类中(不要忘记根据你自己的捆绑包更改名称空间):
< ?php// myapplication/src/sandboxBundle/Command/TestCommand.php// Change the namespace according to your bundlenamespace sandboxBundle\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class TestCommand extends Command{protected function configure(){$this// the name of the command (the part after "bin/console")-> setName('app:test-command')// the short description shown while running "php bin/console list"-> setDescription('Prints some text into the console.')// the full command description shown when running the command with// the "--help" option-> setHelp("This command allows you to print some text in the console"); }protected function execute(InputInterface $input, OutputInterface $output){// outputs multiple lines to the console (adding "\n" at the end of each line)$output-> writeln(['My First Symfony command', // A line'============', // Another line'', // Empty line]); // outputs a message followed by a "\n"$output-> writeln('Hey welcome to the test command wizard.'); $output-> writeln('Thanks for read the article'); // outputs a message without adding a "\n" at the end of the line$output-> write("You've succesfully implemented your first command"); }}

现在, 我们的命令可以执行了。根据configure方法中的定义, 上一条命令的名称为app:test-command, 可以在命令提示符下使用以下行来执行:
php bin/console app:test-command

并在命令提示符下输出:
如何在Symfony 3中创建和执行自定义控制台命令

文章图片
事情并非易事, 现在你了解了命令的工作原理, 就可以创建更复杂的命令了。
处理和设置命令参数(输入) 有时你需要为命令提供一些参数, 例如数字, 标识符, 文本等。
为了允许在命令中使用参数, 我们需要在命令中包括InputArgument类以添加参数, 在configure方法中使用addArgument方法。
< ?php// myapplication/src/sandboxBundle/Command/TestCommand.php// Change the namespace according to your bundlenamespace sandboxBundle\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; // Add the InputArgument classuse Symfony\Component\Console\Input\InputArgument; class TestCommand extends Command{protected function configure(){$this// the name of the command (the part after "bin/console")-> setName('app:print-text')// 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.')// Arguments-> addArgument('text', InputArgument::REQUIRED, 'The text to print'); }protected function execute(InputInterface $input, OutputInterface $output){// outputs multiple lines to the console (adding "\n" at the end of each line)$output-> writeln(['My Second Symfony command', // A line'============', // Another line'', // Empty line]); // Get providen text using the $input-> getArgument method.$text = $input-> getArgument('text'); $output-> writeln("Providen text : ".$text); }}

现在我们的命令已准备好执行。根据configure方法中的定义, 上一个命令的名称将为app:print-text, 并且期望将要打印的字符串作为参数。可以在命令提示符下使用以下行来执行:
php bin/console app:print-text "Hello world, my first argument"

并在命令提示符下输出:
如何在Symfony 3中创建和执行自定义控制台命令

文章图片
处理和设置命令选项(输入参数) 有时你需要像任何现有命令一样, 为命令提供一些参数, 例如数字, 标识符等。默认情况下, 如果参数是先前在命令代码中配置的, 则该命令可以处理这些参数, 否则你将收到错误消息, 例如参数过多或[option]不存在。
要向你的命令添加选项, 我们需要包括InputDefinition和InputOption类, 然后使用setDefinition方法将这些选项添加, 并将这些选项作为数组中InputDefinition的第一个参数添加。
< ?php// myapplication/src/sandboxBundle/Command/TestCommand.php// Change the namespace according to your bundlenamespace sandboxBundle\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; // Add the required classesuse 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())); }}

注意:快捷键的长度不得超过1个字符。如果只需要添加1个参数, 则可以在configure函数中使用setOption方法。
现在我们的命令已准备好执行。如configure方法中所定义, 上一个命令的名称将为app:print-lines, 它期望将要打印的字符串作为参数。可以在命令提示符下使用以下行来执行:
php bin/console app:print-lines --firstline="Hello" --secondline="World"#Or with the shortcutsphp bin/console app:print-lines -a "Hello" -b "World"

集装箱服务 可能你的控制台不仅用于在控制台中编写一些文本。你可以在命令中从容器访问所有服务, 例如, Doctrine, Translator等。
你只需要在命令中包含ContainerAwareCommand类, 而不是扩展Command类, 而需要扩展ContainerAwareCommand类, 则可以按如下所述访问容器, 否则将发现诸如” 尝试调用” 和” 错误” 之类的错误。类YourCommand的未定义方法” getContainer” 。
在这种情况下, 我们将获得Doctrine服务以获取实体管理器并向数据库创建一些查询:
< ?php// myapplication/src/sandboxBundle/Command/TestCommand.php// Change the namespace according to your bundlenamespace sandboxBundle\Command; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; // Add the Containeruse Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; //Extend ContainerAwareCommand instead of Commandclass TestCommand extends ContainerAwareCommand{protected function configure(){$this// the name of the command (the part after "bin/console")-> setName('app:verify-doctrine')// 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.'); }protected function execute(InputInterface $input, OutputInterface $output){$output-> writeln(['My Final Symfony command', // A line'============', // Another line'', // Empty line]); $doctrine = $this-> getContainer()-> get('doctrine'); $em = $doctrine-> getEntityManager(); // Now you can get repositories// $usersRepo = $em-> getRepository("myBundle:Users"); // $user = $usersRepo-> find(1); // outputs multiple lines to the console (adding "\n" at the end of each line)$output-> writeln("Doctrine worked, it didn't crashed :) "); // 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 3中创建和执行自定义控制台命令

文章图片
【如何在Symfony 3中创建和执行自定义控制台命令】请注意, 建议你这样做, 这是创建自己的自定义服务来处理所有逻辑(创建, 编辑, 查找等)的一种好习惯。
总结 可能很难理解控制台应用程序处理自变量的方式, 但是Symfony控制台应用程序与许多其他CLI实用工具一样, 遵循docopt标准中描述的行为。
玩得开心 !

    推荐阅读