个性化阅读
专注于IT技术分析

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

本文概述

Symfony框架通过bin / console脚本提供了许多命令(例如, 众所周知的bin / console cache:clear命令)。这些命令是使用控制台组件创建的。

你还可以使用它使用相同的控制台组件轻松地创建自己的命令, 在本文中, 你将学习如何使用参数和参数创建第一个自定义控制台命令。

你的第一个命令

为了了解所需的结构以及命令的工作方式, 我们将实现你的第一个命令, 该命令基本上会在控制台中打印一些文本。命令是在必须在包的命令命名空间中创建的类中定义的(例如sandboxBundle \ Command), 并且它们的名称必须以Command后缀结尾。

首先, 找到你要在其中创建命令的包(在这种情况下, 我们的包为sandboxBundle), 并在其上创建一个名为Command的文件夹。在Command文件夹中, 创建一个名为TestCommand.php的新类。

你的捆绑包结构应类似于:

带有TestCommand类的Command文件夹

最后, 将以下代码添加到先前创建的类中(不要忘记根据你自己的捆绑包更改名称空间):

<?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

并在命令提示符下输出:

Symfony定制控制台输出

事情并非易事, 现在你了解了命令的工作原理, 就可以创建更复杂的命令了。

处理和设置命令参数(输入)

有时你需要为命令提供一些参数, 例如数字, 标识符, 文本等。

为了允许在命令中使用参数, 我们需要在命令中包括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"

并在命令提示符下输出:

Symfony打印参数

处理和设置命令选项(输入参数)

有时你需要像任何现有命令一样, 为命令提供一些参数, 例如数字, 标识符等。默认情况下, 如果参数是先前在命令代码中配置的, 则该命令可以处理这些参数, 否则你将收到错误消息, 例如参数过多或[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 3命令

请注意, 建议你这样做, 这是创建自己的自定义服务来处理所有逻辑(创建, 编辑, 查找等)的一种好习惯。

总结

可能很难理解控制台应用程序处理自变量的方式, 但是Symfony控制台应用程序与许多其他CLI实用工具一样, 遵循docopt标准中描述的行为。

玩得开心 !

赞(0)
未经允许不得转载:srcmini » 如何在Symfony 3中创建和执行自定义控制台命令

评论 抢沙发

评论前必须登录!