【问题标题】:Symfony Console - Overwrite default optionsSymfony 控制台 - 覆盖默认选项
【发布时间】:2017-08-16 15:36:54
【问题描述】:

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

错误弹出状态

[Symfony\Component\Console\Exception\LogicException] 一个名为“version”的选项已经存在。

【问题讨论】:

  • 默认值是在 Console\Application::getDefaultInputDefinition 中定义的,所以我想你可以创建自己的 Application 类并覆盖。 Application::doRun() 实际上对 --version 进行了硬编码检查,因此您还需要覆盖它。只需选择一个不同的选项名称就容易多了。也许 --package-version 什么的。
  • 是的,我也想过 --package-version ,但老实说,谁想输入呢? ;) 认为我会为此打开一个问题
  • 什么样的问题?按照设计,如果您想要不同的选项,请覆盖。很简单。
  • 如果Application::doRun() 对参数进行硬编码检查,我觉得有些不对劲。 CLI 应用程序的框架不应该强制我不需要某个命令选项。注册一个选项来覆盖任何默认值就足够了。
  • 我真的建议使用不同的选项名称,比如--package-version。您可以尝试覆盖Application 类并将bin/console 复制到加载此应用程序的新命令,但在那之后您仍然有很多障碍。 Symfony 有一个受保护的getDefaultInputDefinition() 函数,您可以覆盖和删除version 选项,但doRun() 命令在其中对version 进行了硬编码检查。您必须在删除现有代码时复制现有代码。

标签: php symfony command-line-interface symfony-console


【解决方案1】:

所以,这里有一个可行的解决方案,但我不推荐它。我建议您简单地使用--package-version 或其他类型的选项作为您的命令,因为这需要大量额外的工作,并且在将来的 Symfony 更新中不能很好地发挥作用。

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

bin/alt_console:

// use Symfony\Bundle\FrameworkBundle\Console\Application;
use AppBundle\Console\Application;

然后创建一个新的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);
    }
}

现在使用您自己的--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
        }
    }
}

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

php bin/console your:command
php bin/console your:comand --version

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

【讨论】:

  • 非常感谢您的广泛回答,但您是对的,我将使用另一个参数名称。我最初发布这个问题是因为我认为我做错了什么。
  • 没问题,这绝对是一个有趣的实验。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 2011-01-18
  • 1970-01-01
相关资源
最近更新 更多