Консоль Symfony — перезаписать параметры по умолчанию

Я создаю приложение CLI для своего приложения, используя Symfony Console. Приложение требуется для выполнения некоторых простых операций по управлению пакетами для управления плагинами. Поэтому мне нужен параметр команды с именем --version с ярлыком -v, что кажется невозможным, поскольку --version зарезервировано для версии приложения, а -v зарезервировано для настройки детализации по умолчанию.
Как я могу отключить параметры по умолчанию или перезаписать их для этой подкоманды?

Всплывающие сообщения об ошибке

[Symfony\Component\Console\Exception\LogicException] Опция с именем «версия» уже существует.


person Moritz Friedrich    schedule 16.08.2017    source источник
comment
Значения по умолчанию определены в Console\Application::getDefaultInputDefinition, поэтому я полагаю, что вы можете создать свой собственный класс приложения и переопределить его. Application::doRun() на самом деле имеет жестко закодированную проверку --version, поэтому вам также нужно будет переопределить ее. Будет намного проще просто выбрать другое имя опции. Может быть --package-version или что-то в этом роде.   -  person Cerad    schedule 16.08.2017
comment
Да, я тоже думал о --package-version, но, честно говоря, кто хочет это напечатать? ;) Думаю, я открою тему для этого   -  person Moritz Friedrich    schedule 16.08.2017
comment
Что за проблема? По дизайну, если вам нужны другие параметры, переопределите их. Достаточно легко.   -  person Cerad    schedule 16.08.2017
comment
Если Application::doRun() имеет жестко закодированную проверку параметра, мне кажется, что-то не так. Фреймворк для приложений CLI не должен навязывать мне определенный параметр команды, который мне не нужен. Должно быть достаточно зарегистрировать опцию для перезаписи любых значений по умолчанию.   -  person Moritz Friedrich    schedule 16.08.2017
comment
Я действительно рекомендую использовать другое имя параметра, например, --package-version. Вы можете попробовать переопределить класс Application и скопировать bin/console в новую команду, которая загружает это приложение, но после этого у вас все равно будет много препятствий. В Symfony есть защищенная функция getDefaultInputDefinition(), которую вы можете переопределить и удалить параметр version, но в команде doRun() есть жестко закодированная проверка на version. Вам придется дублировать существующий код при удалении этого.   -  person Jason Roman    schedule 16.08.2017


Ответы (1)


Итак, вот решение, которое работает, но я не рекомендую его. Я рекомендую вам просто использовать --package-version или какую-либо другую опцию для вашей команды, потому что это требует много дополнительной работы и не подходит для будущих обновлений Symfony.

Первое, что вы можете сделать, это скопировать команду console из каталога bin/ в новую команду и изменить оператор 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 изменятся в будущем, или вам придется вручную обновить эти файлы, поскольку вы их переопределили.

person Jason Roman    schedule 16.08.2017
comment
Я очень ценю ваш обширный ответ, но вы правы, я буду использовать другое имя параметра. Я изначально разместил этот вопрос, потому что думал, что просто делаю что-то не так. - person Moritz Friedrich; 17.08.2017
comment
Нет проблем, это был определенно интересный эксперимент, который стоит попробовать. - person Jason Roman; 17.08.2017