Статьи

Колесо: Консоль Symfony

Я понимаю, что могу быть склонен к написанию собственных решений из-за того, что фокусируюсь на сложных областях, таких как транспорт и платежи, где требуется новый код для обеспечения конкурентного преимущества. В этой новой серии «Колесо» я исследую проекты с открытым исходным кодом из мира PHP, чтобы создать и предоставить вам знания о существующих инструментах: давайте вместе бороться с синдромом « Не изобретено здесь» и не будем изобретать колесо .

На этой неделе я собираюсь изучить консоль Symfony .

Компоненты Symfony

Symfony — одна из самых популярных платформ PHP с открытым исходным кодом на рынке. Компоненты Symfony, однако, являются слабо связанными проектами, которые можно повторно использовать в качестве библиотеки вне приложения, основанного на Symfony.

Компонент, рассматриваемый в этой статье, — Console (symfony / console на Packagist и GitHub ), предназначенный для быстрой сборки консольных приложений; Я недавно внес свой вклад в обертку PHPUnit Paratest, которая построена вместе с ней. Как и большинство (или все?) Компонентов Symfony, он не имеет зависимостей; даже если бы они присутствовали, я бы позаботился об этом с помощью Composer (тема нашей следующей статьи).

Плюсы

Давайте оценим, почему вы должны использовать консоль Symfony для своих скриптов или приложений командной строки. Прежде всего вы должны решить, является ли пользовательский интерфейс командной строки стратегическим или служебным аспектом вашего проекта: во всех случаях, когда в нем нет конкурентного преимущества, передача большей части кода библиотеке является рентабельной. Если пользователи решают переключиться на ваше приложение по другим причинам, а не по интерфейсу, вам лучше сэкономить время в этом разделе кода и посвятить его своему базовому домену.

Вы получаете функциональность бесплатно. Учитывая этот код из документации:

class GreetCommand extends Command
{
  protected function configure()
  {
      $this
          ->setName('demo:greet')
          ->setDescription('Greet someone')
          ->addArgument(
              'name',
              InputArgument::OPTIONAL,
              'Who do you want to greet?'
          )
          ->addOption(
              'yell',
              null,
              InputOption::VALUE_NONE,
              'If set, the task will yell in uppercase letters'
          );
  }

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

И вы получаете почти все, что вам когда-либо нужно из скрипта: команды, аргументы и параметры.

[08:11:05][root@onebipdev:~/console_example]$ ./app.php demo:greet
Hello
[08:11:11][root@onebipdev:~/console_example]$ ./app.php demo:greet Giorgio
Hello Giorgio
[08:11:14][root@onebipdev:~/console_example]$ ./app.php demo:greet --yell Giorgio
HELLO GIORGIO

На самом деле, вы можете добавить несколько команд, отличных от demo: greet, настроив объекты:

$application = new Application();
$application->add(new GreetCommand);
$application->run();

И мне очень нравится, что Symfony Components являются лидерами стандарта PSR-0, и вы можете создавать функциональность, явно составляя объекты вместо размещения скриптов и классов в специальных папках, как во многих средах первого поколения.

Вы также получаете бесплатно интерфейс с некоторым удобством использования. Вот что запускает `. / App.php` без какой-либо выбранной команды:

$ ./app.php
Console Tool

Usage:
  [options] command [arguments]

Options:
  --help  -h Display this help message.
  --quiet  -q Do not output any message.
  --verbose  -v Increase verbosity of messages.
  --version  -V Display this application version.
...

Available commands:
  help  Displays help for a command
  list  Lists commands

Стандартное оформление этого вывода характерно для приложений, созданных с помощью Symfony Console, и разработчикам PHP приятно видеть знакомый экран справки.

Управление ошибками также включено в цену. В случае неперехваченного исключения процесс не завершается трассировкой стека, а вместо этого отображается исключение:

$ ./app.php demo:greet
  [RuntimeException]   
  Sorry, the thread has gone askew on the kettle  
demo:greet [--yell] [name]
(blanks redacted for space)

(Потенциальные) минусы

Благодаря великолепной документации я лучше узнал консоль Symfony менее чем за час . Однако всегда существует компромисс между пользовательским и открытым исходным кодом: нужно пожертвовать чем-то, чтобы получить эти функциональные возможности бесплатно.

Первый компромисс между простотой и размером : для небольших приложений и одноразовых сценариев захват 10 839 строк кода — это большие издержки, даже если Composer делает это легко. getopt () неясен, но только на 6 букв; с увеличением количества команд и параметров Symfony Console лучше масштабируется.

Второй компромисс — классический вариант инверсии контроля: вы отказываетесь от управления основным потоком вашего приложения в рамках, где вам нужно заполнить недостающие фрагменты. Этот уровень косвенности полезен для функциональных возможностей, которые он предоставляет, но добавляет сложность для всех ваших трассировок стека и результатов профилирования.

Последний компромисс заключается в том, что вы должны согласиться с решениями, принятыми самоуверенными библиотеками; например, —help — это стандартная команда, которую вы должны будете принять в своем скрипте именно в этом формате. В принципе, в поддержке справки и списка нет ничего плохого , но выбор библиотеки примет решение за вас.