Tworzenie sparametryzowanych komend w PHP z komponentem Console Symfony2

Ten wpis został napisany dawno temu i może być już nieaktualny.

Komponent Console Symfony2 ułatwia tworzenie sparametryzowanych komend w PHP. Odpowiada za niewdzięczną pracę parsowania wejścia i pisania na wyjście. Uwaga: Kod tworzony w tym wpisie jest dostępny na githubie: https://github.com/jakzal/SymfonyComponentsExamples

Instalacja

Komponent możemy zainstalować za pomocą kanału PEAR Symfony2 lub go po prostu pobrać z githuba. Na potrzeby tego wpisu sklonujemy źródła do katalogu vendor/ naszego projektu.

git clone https://github.com/symfony/Console.git vendor/Symfony/Component/Console

Użyjemy ClassLoader, innego komponentu Symfony2, do automatycznego ładowania klas. Więcej o tym komponencie we wpisie  "Automatyczne ładowanie klas w dowolnym projekcie PHP z komponentem ClassLoader Symfony2". Poniższy kod wystarczy, aby wszystkie klasy z dowolnego komponentu Symfony2 były automatycznie ładowane (zakładając, że komponenty są umieszczane w katalogu vendor/Symfony/Component):

<?php
// src/autoload.php
require_once __DIR__.'/../vendor/Symfony/Component/ClassLoader/UniversalClassLoader.php';

$loader = new Symfony\Component\ClassLoader\UniversalClassLoader();
$loader->registerNamespaces(array(
    'Symfony' => __DIR__.'/../vendor',
    'PSS'     => __DIR__
));
$loader->register();

Przestrzeń nazw PSS posłuży naszym klasom.

Tworzenie aplikacji konsolowej

Aplikacja konsolowa pomoże nam zarządzać komendami:

<?php
// console.php
require_once __DIR__.'/src/autoload.php';

use Symfony\Component\Console as Console;

$application = new Console\Application('Demo', '1.0.0');
$application->run();

Jeśli uruchomimy skrypt bez argumentów, zobaczymy przegląd domyślnych opcji i komend.

Istnieją dwie wbudowane komendy: help i list.

Tworzenie komendy

Komendę tworzymy rozszerzając klasę Command i implementując w niej metodę execute().

<?php
// src/PSS/Command/HelloWorldCommand.php
namespace PSS\Command;

use Symfony\Component\Console as Console;

class HelloWorldCommand extends Console\Command\Command
{
    protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
    {
        $output->writeln('Hello World!');
    }
}

Metoda przyjmuje obiekty wejścia i wyjścia jako parametry ($input i $output). Obiektu wejścia będziemy używać, aby dostać się do argumentów i opcji przekazanych do skryptu. Obiekt wyjścia jest pomocy przy drukowaniu komunikatów (np na ekran). Każda komenda musi być zarejestrowana w aplikacji:

<?php
// console.php
require_once __DIR__.'/src/autoload.php';

use Symfony\Component\Console as Console;

$application = new Console\Application('Demo', '1.0.0');
**$application->add(new PSS\Command\HelloWorldCommand('hello-world'));**
$application->run();

Skrypt przyjmuje nazwę komendy jako pierwszy argument . Naszą komendę wywołamy przez:

php console.php hello-world

W wyniku powinniśmy zobaczyć "Hello World!" wypisane na ekran.

Dodajemy argumenty i opcje

Argumentów i opcji możemy użyć, aby sparametryzować i zmienić zachowanie naszej komendy. Zmodyfikujemy komendę HelloWorld, aby przyjmowała imię jako parametr. Wydrukujemy je później na ekran. Dodamy też opcję "--more", która sprawi, że komenda wypisze dodatkowy komunikat. Argumenty i opcje, które chcemy móc przekazywać do komendy, deklarujemy odpowiednio metodami addArgument() i addOption(). Możemy uczynić je opcjonalnymi lub wymaganymi, dodać opis i wartości domyślne. Podane w linii poleceń parametry pobieramy po prostu z obiektu wejścia ($input) przekazanego do metody execute() (Aplikacja konsolowa zajmie się szczegółami).

<?php
// src/PSS/Command/HelloWorldCommand.php
namespace PSS\Command;

use Symfony\Component\Console as Console;

class HelloWorldCommand extends Console\Command\Command
{
    public function __construct($name = null)
    {
        parent::__construct($name);

        $this->setDescription('Outputs welcome message');
        $this->setHelp('Outputs welcome message.');
        $this->addArgument('name', Console\Input\InputArgument::OPTIONAL, 'The name to output to the screen', 'World');
        $this->addOption('more', 'm', Console\Input\InputOption::VALUE_NONE, 'Tell me more');
    }

    protected function execute(Console\Input\InputInterface $input, Console\Output\OutputInterface $output)
    {
        $name = $input->getArgument('name');

        $output->writeln(sprintf('Hello %s!', $name));

        if ($input->getOption('more')) {
            $output->writeln('It is really nice to meet you!');
        }
    }
}

Teraz możemy użyć nowo dodanego argumentu i opcji:

php console.php hello-world -m Kuba

Dodatkowe wywołania setDescription() i setHelp() w konstruktorze ustawiają opis komendy i komunikat pomocy. Są bardzo przydatne, gdy nasz skrypt ma być używany przez innych. Pomoc uzyskamy wywołując komendę help z nazwą naszej komendy przekazaną jako argument:

php console.php help hello-world

Interaktywna powłoka

Poprzez opakowanie aplikacji konsolowej obiektem klasy Shell, łatwo zyskamy funkcjonalność interaktywnej powłoki:

<?php
// consoleshell.php
require_once __DIR__.'/src/autoload.php';

use Symfony\Component\Console as Console;

$application = new Console\Application('Demo', '1.0.0');
$application->add(new PSS\Command\HelloWorldCommand('hello-world'));

$shell = new Console\Shell($application);
$shell->run();

W ten sposób skrypt nie zakończy działania zaraz po uruchomieniu, ale będzie czekał na nasze komendy:

php consoleshell.php

Jakub Zalas

Jakub Zalas

Architekt, Programista, Trener