ZetCode

Symfony 控制台命令

最后修改于 2020 年 7 月 5 日

Symfony 控制台命令教程展示了如何在 Symfony 中创建控制台命令。我们将为一个控制台应用程序创建几个命令。

Symfony

Symfony 是一套可重用的 PHP 组件,也是一个用于 Web 项目的 PHP 框架。Symfony 于 2005 年发布为自由软件。Symfony 的最初作者是 Fabien Potencier。Symfony 深受 Spring Framework 的启发。

Symfony 控制台组件

Symfony 控制台组件允许我们创建命令行命令。控制台命令可用于创建计划任务、导入、批处理作业或一些支持性任务。Symfony 控制台命令可以在 Symfony 控制台应用程序或 Web 应用程序中使用。在本教程中,我们将为控制台应用程序创建命令。

Symfony 控制台命令示例

在下面的示例中,我们使用 Symfony 控制台组件创建一个 Symfony 控制台应用程序。

$ mkdir commands
$ cd commands

我们创建一个项目目录并进入其中。

$ composer require symfony/console

我们安装 console 包。

composer.json
{
    "name": "Symfony command application",
    "description": 
    "This application demonstrates the usage of a Symfony command in a console application",
    "require": {
        "symfony/console": "^4.2"
    },
    "autoload": {
        "psr-4": {
            "App\\": "src"
        }
    }
}

我们更新 composer.json 文件。我们启用位于 src 目录下的 PHP 类的自动加载,命名空间为 App

$ composer dump-autoload -o

创建完文件后,我们需要调用 composer dump-autoload -o 命令,该命令会创建一个将类映射到 PHP 文件的文件。

在应用程序中,我们将有五个命令

命令在 src/Command 目录中创建。命令必须继承 Symfony\Component\Console\Command 并实现其 configure()execute() 方法。

稍后,使用 add() 方法将命令添加到 Symfony\Component\Console\Application 中。

src/Command/TimeCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class TimeCommand extends Command 
{
    protected function configure()
    {
        $this->setName('time')
        ->setDescription('Shows current date and time')
        ->setHelp('This command prints the current date and time');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $now = date('c');
        $message = sprintf("Current date and time: %s", $now);

        $output->writeln($message);
    }
}

TimeCommand 显示当前的日期和时间。

protected function configure()
{
    $this->setName('time')
    ->setDescription('Shows current date and time')
    ->setHelp('This command prints the current date and time');
}

configure() 方法中,我们使用 setName() 设置命令的名称。该名称将显示在可用命令列表中。我们还为命令添加了描述和帮助信息。

protected function execute(InputInterface $input, OutputInterface $output)
{
    $now = date('c');
    $message = sprintf("Current date and time: %s", $now);

    $output->writeln($message);
}

InputInterface 用于获取用户输入,OutputInterface 用于显示输出。在我们的例子中,我们使用 date() 获取当前日期和时间,格式为标准的 ISO 格式,并使用 writeln() 将其输出到控制台。

src/Command/MessageCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;

class MessageCommand extends Command
{
    protected function configure()
    {
        $this->setName('msg')
            ->setDescription('Prints a user provided message')
            ->setHelp('This command prints a message provided by the user')
            ->addArgument('msg', InputArgument::REQUIRED, 'Pass a message');
    }
 
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $message = sprintf('The message is: %s', $input->getArgument('msg'));
        $output->writeln($message);
    }
}

MessageCommand 打印从用户参数中获取的消息,并将其输出到控制台。

$this->setName('msg')
    ->setDescription('Prints a user provided message')
    ->setHelp('This command prints a message provided by the user')
    ->addArgument('msg', InputArgument::REQUIRED, 'Pass a message');

参数可以是必需的,也可以是可选的。InputArgument::REQUIRED 值使参数成为必需的。

$message = sprintf('The message is: %s', $input->getArgument('msg'));
$output->writeln($message);

我们使用 getArgument() 从输入中检索参数,并使用 writeln() 将其写入控制台。

src/Command/ColorCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Formatter\OutputFormatterStyle;

class ColorCommand extends Command
{
    protected function configure()
    {
        $this->setName('colc')
            ->setDescription('Shows output in color')
            ->setHelp('This command shows output in color');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {

        $output->writeln("<info>Today is a windy day</info>");

        $outputStyle = new OutputFormatterStyle('red');
        $output->getFormatter()->setStyle('redt', $outputStyle);

        $output->writeln('<redt>Tomorrow will be snowing</redt>');
    }
}

ColorCommand 以彩色显示文本。

$output->writeln("<info>Today is a windy day</info>");

在这种情况下,我们使用内置的 info 格式样式。

$outputStyle = new OutputFormatterStyle('red');
$output->getFormatter()->setStyle('redt', $outputStyle);

$output->writeln('<redt>Tomorrow will be snowing</redt>');

我们也可以使用 OutputFormatterStyle 创建自定义输出样式。我们的 redt 以红色显示文本。

src/Command/BooksCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class BooksCommand extends Command
{
    protected function configure() 
    {
        $this->setName('books')
            ->setDescription('Shows books in a table')
            ->setHelp('This command demonstrates the usage of a table helper');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $table = new Table($output);
        
        $table->setHeaderTitle('Books')
            ->setHeaders(['Title', 'ISBN', 'Author', 'Publisher'])
            ->setRows([
                ['Java Language Features', '978-1-4842-3347-4', 'Kishori Sharan', 'Apress' ],
                ['Python Testing with pytest', '978-1-68-050-240-4', 'Brian Okken', 'The Pragmatic Programmers' ],
                ['Deep Learning with Python', '978-1-61729-443-3', 'Francois Chollet', 'Manning' ],
                ['Laravel up & Running', '978-1-491-93698-5', 'Matt Stauffer', 'O\'Reilly' ],
                ['Sams Teach Yourself TCP/IP', '978-0-672-33789-5', 'Joe Casad', 'SAMS' ]
            ]);

          $table->render();
    }   
}

BooksCommand 使用表格助手以表格格式输出数据。

$table = new Table($output);

我们创建一个 Table 助手实例。

$table->setHeaderTitle('Books')
    ->setHeaders(['Title', 'ISBN', 'Author', 'Publisher'])
    ->setRows([
        ['Java Language Features', '978-1-4842-3347-4', 'Kishori Sharan', 'Apress' ],
        ['Python Testing with pytest', '978-1-68-050-240-4', 'Brian Okken', 'The Pragmatic Programmers' ],
        ['Deep Learning with Python', '978-1-61729-443-3', 'Francois Chollet', 'Manning' ],
        ['Laravel up & Running', '978-1-491-93698-5', 'Matt Stauffer', 'O\'Reilly' ],
        ['Sams Teach Yourself TCP/IP', '978-0-672-33789-5', 'Joe Casad', 'SAMS' ]
    ]);

我们构建表格。表格的标题通过 setHeaderTitle() 指定。header 名称通过 setHeaders() 指定。最后,通过 setRows() 添加数据。

$table->render();

表格通过 render() 渲染。

src/Command/AskNameCommand.php
<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class AskNameCommand extends Command
{
    protected function configure() 
    {
        $this->setName('ask')
            ->setDescription('Interactively asks name from the user')
            ->setHelp('This command asks a user name interactively and prints it');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $helper = $this->getHelper('question');
        $question = new Question("Enter your name: ", "guest");

        $name = $helper->ask($input, $output, $question);
        $message = sprintf("Hello %s!", $name);

        $output->writeln($message);
    }
}

AskNameCommand 使用问题助手向用户提问。

$helper = $this->getHelper('question');

通过 getHelper() 创建一个问题助手。

$question = new Question("Enter your name: ", "guest");

创建一个新的 Question 问题。第二个参数是默认值。

$name = $helper->ask($input, $output, $question);

使用 ask() 激活问题。用户输入存储在 $name 变量中。

$message = sprintf("Hello %s!", $name);

我们使用 sprintf() 根据用户输入构建一条消息。

$output->writeln($message);

最后,使用 writeln() 在终端显示消息。

使用 Symfony\Component\Console\Application 创建一个新的 Symfony 应用程序。

Application.php
<?php

require __DIR__ . '/vendor/autoload.php';

use App\Command\TimeCommand;
use App\Command\BooksCommand;
use App\Command\ColorCommand;
use App\Command\AskNameCommand;
use App\Command\MessageCommand;
use Symfony\Component\Console\Application;

$app = new Application();

$app->add(new MessageCommand());
$app->add(new TimeCommand());
$app->add(new AskNameCommand());
$app->add(new BooksCommand());
$app->add(new ColorCommand());

$app->run();

我们创建了一个包含五个命令的 Symfony 控制台应用程序。

$app = new Application();

创建了一个新的控制台应用程序。

$app->add(new MessageCommand());
$app->add(new TimeCommand());
$app->add(new AskNameCommand());
$app->add(new BooksCommand());
$app->add(new ColorCommand());

我们将命令添加到应用程序中。

$app->run();

使用 run() 启动应用程序。

$ php application.php list
Console Tool
...
Available commands:
    ask    Interactively asks name from the user
    books  Shows books in a table
    colc   Shows output in color
    help   Displays help for a command
    list   Lists commands
    msg    Prints a user provided message
    time   Shows current date and time

我们可以获取我们命令的列表。

$ php application.php books
+----------------------------+--------------- Books -----------------+---------------------------+
| Title                      | ISBN               | Author           | Publisher                 |
+----------------------------+--------------------+------------------+---------------------------+
| Java Language Features     | 978-1-4842-3347-4  | Kishori Sharan   | Apress                    |
| Python Testing with pytest | 978-1-68-050-240-4 | Brian Okken      | The Pragmatic Programmers |
| Deep Learning with Python  | 978-1-61729-443-3  | Francois Chollet | Manning                   |
| Laravel up & Running       | 978-1-491-93698-5  | Matt Stauffer    | O'Reilly                  |
| Sams Teach Yourself TCP/IP | 978-0-672-33789-5  | Joe Casad        | SAMS                      |
+----------------------------+--------------------+------------------+---------------------------+

我们运行 books 命令。

$ php application.php time
Current date and time: 2018-12-20T23:27:16+01:00

我们运行 time 命令。

在本教程中,我们在 Symfony 控制台应用程序中创建了五个控制台命令。

$ php application.php ask
Enter your name: Peter
Hello Peter!

我们运行 ask 命令。

在本教程中,我们在 Symfony 控制台应用程序中创建了五个控制台命令。

列出 所有 Symfony 教程。