本文概述
Symfony框架通过bin / console脚本提供了许多命令(例如, 众所周知的bin / console cache:clear命令)。这些命令是使用控制台组件创建的。
你还可以使用它使用相同的控制台组件轻松地创建自己的命令, 在本文中, 你将学习如何使用参数和参数创建第一个自定义控制台命令。
你的第一个命令
为了了解所需的结构以及命令的工作方式, 我们将实现你的第一个命令, 该命令基本上会在控制台中打印一些文本。命令是在必须在包的命令命名空间中创建的类中定义的(例如sandboxBundle \ Command), 并且它们的名称必须以Command后缀结尾。
首先, 找到你要在其中创建命令的包(在这种情况下, 我们的包为sandboxBundle), 并在其上创建一个名为Command的文件夹。在Command文件夹中, 创建一个名为TestCommand.php的新类。
你的捆绑包结构应类似于:
最后, 将以下代码添加到先前创建的类中(不要忘记根据你自己的捆绑包更改名称空间):
<?php
// myapplication/src/sandboxBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace 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
并在命令提示符下输出:
事情并非易事, 现在你了解了命令的工作原理, 就可以创建更复杂的命令了。
处理和设置命令参数(输入)
有时你需要为命令提供一些参数, 例如数字, 标识符, 文本等。
为了允许在命令中使用参数, 我们需要在命令中包括InputArgument类以添加参数, 在configure方法中使用addArgument方法。
<?php
// myapplication/src/sandboxBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace sandboxBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
// Add the InputArgument class
use 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"
并在命令提示符下输出:
处理和设置命令选项(输入参数)
有时你需要像任何现有命令一样, 为命令提供一些参数, 例如数字, 标识符等。默认情况下, 如果参数是先前在命令代码中配置的, 则该命令可以处理这些参数, 否则你将收到错误消息, 例如参数过多或[option]不存在。
要向你的命令添加选项, 我们需要包括InputDefinition和InputOption类, 然后使用setDefinition方法将这些选项添加, 并将这些选项作为数组中InputDefinition的第一个参数添加。
<?php
// myapplication/src/sandboxBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace sandboxBundle\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()));
}
}
注意:快捷键的长度不得超过1个字符。如果只需要添加1个参数, 则可以在configure函数中使用setOption方法。
现在我们的命令已准备好执行。如configure方法中所定义, 上一个命令的名称将为app:print-lines, 它期望将要打印的字符串作为参数。可以在命令提示符下使用以下行来执行:
php bin/console app:print-lines --firstline="Hello" --secondline="World"
#Or with the shortcuts
php 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 bundle
namespace sandboxBundle\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
// Add the Container
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
//Extend ContainerAwareCommand instead of Command
class 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控制台应用程序与许多其他CLI实用工具一样, 遵循docopt标准中描述的行为。
玩得开心 !
评论前必须登录!
注册