Symfony控制台 - 覆盖默认选项

Mor*_*ich 5 php command-line-interface symfony symfony-console

我正在使用Symfony控制台为我的应用程序构建CLI应用程序.应用程序需要执行一些简单的包管理操作来管理插件.因此,我需要一个--version以快捷方式命名的命令选项-v,这似乎不可能,因为它--version是为应用程序版本-v保留的,并保留用于默认的详细程度设置.
如何禁用默认选项或为此子命令覆盖它们?

错误弹出状态

[Symfony\Component\Console\Exception\LogicException]名为"version"的选项已存在.

Jas*_*man 3

所以,这是一个可行的解决方案,但我不推荐它。我建议您简单地使用--package-version或其他类型的命令选项,因为这需要大量额外的工作,并且对于未来的 Symfony 更新来说效果不佳。

您可以做的第一件事是将目录console中的命令复制bin/到新命令,并将use语句更改为您自己的扩展应用程序:

bin/alt_console:

// use Symfony\Bundle\FrameworkBundle\Console\Application;
use AppBundle\Console\Application;
Run Code Online (Sandbox Code Playgroud)

然后创建一个Application扩展现有 Symfony 应用程序的新类,如下所示:

应用:

namespace AppBundle\Console;

use AppBundle\Command\YourCommand;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Event\ConsoleErrorEvent;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

class TestApplication extends Application
{
    const NAME = 'Alternative Application';
    const VERSION = '1.0';

    // these are normally private, but must now be protected as they exist in doRun()
    protected $command;
    protected $defaultCommand;
    protected $dispatcher;
    protected $runningCommand;

    /**
     * {@inheritdoc}
     */
    public function __construct()
    {
        parent::__construct(static::NAME, static::VERSION);

        // manually add the commands you want to be handled by this
        $this->add(new YourCommand());
    }

    /**
     * {@inheritdoc}
     */
    public function doRun(InputInterface $input, OutputInterface $output)
    {
        /* remove these lines
        if (true === $input->hasParameterOption(array('--version', '-V'), true)) {
            $output->writeln($this->getLongVersion());

            return 0;
        }
        */

        // copy the rest of the doRun() function as it 
        // exists in the base Application class
        // ...
    }

    /**
     * {@inheritdoc}
     *
     * Return everything from the default input definition except the 'version' option
     */
    protected function getDefaultInputDefinition()
    {
        $definition  = [];

        $defaultDefinition = parent::getDefaultInputDefinition();

        foreach ($defaultDefinition->getOptions() as $option) {
            if ($option->getName() !== 'version') {
                $definition[] = $option;
            }
        }

        foreach ($defaultDefinition->getArguments() as $argument) {
            $definition[] = $argument;
        }

        return new InputDefinition($definition);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在使用您自己的--version选项添加您的应用程序:

namespace AppBundle\Command;

use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

class YourCommand extends ContainerAwareCommand
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('your:command')
            ->addOption('--version', '-V', InputOption::VALUE_NONE, 'okay')
        ;
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if ($input->hasOption('version')) {
            // do something
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以通过以下方式调用你的命令:

php bin/console your:command
php bin/console your:comand --version
Run Code Online (Sandbox Code Playgroud)

请注意,我不推荐这样做。这是大量的额外工作,除了现在使用不同的选项为自己节省几次击键之外,几乎没有任何好处。另外,如果bin/console将来Symfony\Component\Console\Application发生变化,或者您将必须手动更新这些文件,因为您覆盖了它们。