命令行
Symfony框架通過bin/console
腳本(如,廣為人知的bin/console cache:clear
命令)提供了大量命令。這些命令是通過控制臺組件被創(chuàng)建的。你也可以使用它創(chuàng)建自己的命令。
創(chuàng)建一個命令 ?
命名通過類來定義,這些類必須存放在你的束(如AppBundle\Command
)的Command
命名空間下。類名必須是Command
后綴。
例如,一個名為CreateUser
的命令必須遵循此結(jié)構(gòu):
// src/AppBundle/Command/CreateUserCommand.phpnamespace AppBundle\Command; use Symfony\Component\Console\Command\Command;use Symfony\Component\Console\Input\InputInterface;use Symfony\Component\Console\Output\OutputInterface; class CreateUserCommand extends Command{ protected function configure() { // ... } protected function execute(InputInterface $input, OutputInterface $output) { // ... }}
配置命令 ?
首先,你必須在configure()
方法中配置命令的名稱。然后可選地定義一個幫助信息(幫助消息)和輸入選項及輸入?yún)?shù)(輸入選項和參數(shù)):
// ...protected function configure(){ $this // the name of the command (the part after "bin/console") // 命令的名字("bin/console" 后面的部分) ->setName('app:create-users') // the short description shown while running "php bin/console list" // 運行 "php bin/console list" 時的簡短描述 ->setDescription('Creates new users.') // the full command description shown when running the command with // the "--help" option // 運行命令時使用 "--help" 選項時的完整命令描述 ->setHelp("This command allows you to create users...") ;}
執(zhí)行命令 ?
配置命令之后,你就能在終端(終端)中執(zhí)行它:
$ php bin/console app:create-users
你可以已經(jīng)預(yù)期,這個命令將什么也不做,因為你還沒有寫入任何邏輯。在execute()
方法里添加你自己的邏輯,這個方法可以訪問到輸入流(如,選項和參數(shù))和輸出流寫入信息到命令行):
// ...protected function execute(InputInterface $input, OutputInterface $output){ // outputs multiple lines to the console (adding "\n" at the end of each line) // 輸出多行到控制臺(在每一行的末尾添加 "\n") $output->writeln([ 'User Creator', '============', '', ]); // outputs a message followed by a "\n" $output->writeln('Whoa!'); // outputs a message without adding a "\n" at the end of the line $output->write('You are about to '); $output->write('create a user.');}
現(xiàn)在,嘗試執(zhí)行此命令:
$ php bin/console app:create-user User Creator============ Whoa!You are about to create a user.
控制臺輸入 ?
使用輸入選項或參數(shù)來傳入信息給命令:
use Symfony\Component\Console\Input\InputArgument; // ...protected function configure(){ $this // configure an argument / 配置一個參數(shù) ->addArgument('username', InputArgument::REQUIRED, 'The username of the user.') // ... ;} // ...public function execute(InputInterface $input, OutputInterface $output){ $output->writeln([ 'User Creator', '============', '', ]); // retrieve the argument value using getArgument() // 使用 getArgument() 取出參數(shù)值 $output->writeln('Username: '.$input->getArgument('username'));
現(xiàn)在,你可以傳入用戶名到命令中:
$ php bin/console app:create-user Wouter User Creator============ Username: Wouter
參考控制臺輸出(參數(shù)和選項)以了解更多關(guān)于命令行選項和參數(shù)的信息。
從服務(wù)容器中取得服務(wù) ?
要真正創(chuàng)建用戶,命令必須要訪問某些服務(wù)(服務(wù))。這可以通過讓命令繼承ContainerAwareCommand
來實現(xiàn):
// ...use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; class CreateUserCommand extends ContainerAwareCommand{ // ... protected function execute(InputInterface $input, OutputInterface $output) { // ... // access the container using getContainer() // 使用 getContainer() 訪問服務(wù)容器 $userManager = $this->getContainer()->get('app.user_manager'); $userManager->create($input->getArgument('username')); $output->writeln('User successfully generated!'); }}
現(xiàn)在,一旦你創(chuàng)建了所需的服務(wù)及其邏輯,命令將執(zhí)行app.user_manager
服務(wù)的create()
方法,然后用戶會被創(chuàng)建的命令生命周期
命令有三個生命周期方法可以在運行命令時使用:
initialize()
(可選)- 這個方法在
interact()
和execute()
方法之前執(zhí)行。它的主要作用是初始化那些用在命令其余方法中的變量。 interact()
(可選)- 此方法在
initialize()
之后、execute()
之前執(zhí)行。它的作用是檢查是否錯失了某些選項/參數(shù),然后以互動方式向用戶請求這些值。這是你可以問詢錯失的選項/參數(shù)的最后一個地方。此后,丟失的選項/參數(shù)將導(dǎo)致一個錯誤。 execute()
(必須)- 此方法在
interact()
andinitialize()
之后執(zhí)行。它包含你希望命令去執(zhí)行的邏輯。
測試命令 ?
Symfony提供了幾個工具來幫你測試命令。最有用的一個是 CommandTester
類。它使用特殊的input和output類,令“不在真正控制臺中”的測試變得容易:
// tests/AppBundle/Command/CreateUserCommandTest.phpnamespace Tests\AppBundle\Command; use AppBundle\Command\CreateUserCommand;use Symfony\Bundle\FrameworkBundle\Console\Application;use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;use Symfony\Component\Console\Tester\CommandTester; class CreateUserCommandTest extends KernelTestCase{ public function testExecute() { self::bootKernel(); $application = new Application(self::$kernel); $application->add(new CreateUserCommand()); $command = $application->find('app:create-user'); $commandTester = new CommandTester($command); $commandTester->execute(array( 'command' => $command->getName(), // pass arguments to the helper / 傳入?yún)?shù)給helper 'username' => 'Wouter', // prefix the key with a double slash when passing options, // e.g: '--some-option' => 'option_value', // 需要選項時,對key加“雙中杠”的前綴,如'--some-option' => 'option_value' )); // the output of the command in the console // 控制臺中的命令輸出 $output = $commandTester->getDisplay(); $this->assertContains('Username: Wouter', $output); // ... }}
使用 ApplicationTester
你也可以測試整個控制臺程序。
當(dāng)Console組件被單獨使用時,使用 Symfony\Component\Console\Application
和常規(guī)的 \PHPUnit_Framework_TestCase
。
要在你的console tests中使用最完整的服務(wù)容器設(shè)置,你可以從 KernelTestCase
中繼承你的測試:
// ...use Symfony\Component\Console\Tester\CommandTester;use Symfony\Bundle\FrameworkBundle\Console\Application;use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; class CreateUserCommandTest extends KernelTestCase{ public function testExecute() { $kernel = $this->createKernel(); $kernel->boot(); $application = new Application($kernel); $application->add(new CreateUserCommand()); $command = $application->find('app:create-user'); $commandTester = new CommandTester($command); $commandTester->execute(array( 'command' => $command->getName(), 'username' => 'Wouter', )); $output = $commandTester->getDisplay(); $this->assertContains('Username: Wouter', $output); // ... }}
控制臺助手
Console組件還包括了一組“助手”(helpers)——不同的小工具可以幫助你完成不同的任務(wù):
- Question Helper(提問助手): interactively ask the user for information
- Formatter Helper(格式助手): customize the output colorization
- Progress Bar(進(jìn)度條): shows a progress bar
- Table(表格): displays tabular data as a table