Skrypty konsolowe w aplikacji ZF2
Zend Framework 2 (od niedawna dostępny w wersji stabilnej) wśród licznych nowości przyniósł jedną, która bardzo mi się podoba i zawsze mi jej brakowało. Chodzi o wbudowaną obsługę skryptów konsolowych. Czyli poleceń w aplikacji, które z poziomu konsoli można wywoływać. Mogą to być akcje odpalane z crona, zarządzanie aplikacją, włączanie trybu maintenance, sprawdzenie stanu system czy cokolwiek jest potrzebne. Całość jest bardzo łatwa do skonfigurowania, a uruchomienie sprowadza się do wykonania przez php głównego skryptu index.php (chociaż ja wolę utworzyć do tego dodatkowy skrypt).
Konfiguracja
Konfiguracja obywa się analogicznie do konfiguracji zwykłych routerów HTTP, czyli zazwyczaj w plikach module.config.php poszczególnych modułów. Jest ona dodatkowo zagnieżdżona na głównym poziomie w kluczu console, a dopiero w nim znajduje się klucz router i routes.
return array( 'console' => array( 'router' => array( 'routes' => array( 'user-create' => array( 'options' => array( 'route' => 'user create [--verbose|-v] <userEmail>', 'defaults' => array( 'controller' => 'MyApp\Controller\Users', 'action' => 'create', ), ), ), ), ), ), );
Jak widać konfiguracja jest bardzo podobna do standardowych: zawiera ścieżkę routingu i domyślne parametry. Nieco inaczej konfiguruje się właśnie parametry. Nie ma tutaj takiego formatu jak w routerze Segment, czyli :nazwa. Parametry możemy podadać na różne sposoby, a składnia przypomina standardową składnie podawaną w pomocy i dokumentacji wielu poleceń linuksowych. powyższy przykład umożliwia ustawienie dwóch parametrów: verbose (skrótowo v), który jest flagą true/false (podany/niepodany) oraz userEmail, który jest parametrem tekstowym, czyli pod zmienną dostępna będzie zawartość wpisana w poleceniu.
Do dyspozycji mamy kilka rodzajów parametrów:
- polecenia tekstowe – stałe teksty, które mogą być wpisane albo być nieobowiązkowe oraz mogą posiadać alternatywy, np. user (create|delete) spowoduje, że zarówno polecenie user create jak i user delete będą akceptowane. Polecenia te będą dostępne jako parametry flagowe,
- flagi – pokazane w przykładzie wyżej, działają podobnie jak polecenia tekstowe ale mają inne formatowanie – myślniki z przodu. Również mogą być obowiązkowe lub nie oraz posiadać alternatywy,
- parametry z wartością – pokazane na przykładzie userEmail, mogę mieć formę parametru tekstowego lub opcji –nazwa=wartosc,
- grupy parametrów – specjalny zapis łączący powyższe funkcje i pozwalający na zapisywanie parametrów pod nazwami.
Pełne szczegóły na temat dostępnych formatów wraz z opisem oraz przykładami znajdują się w oficjalnej dokumentacji.
Uruchomienie
Uruchamianie skryptów jest bardzo łatwe. Sprowadza się do wykonania przez konsolowy interpreter php głównego pliku public/index.php. I to wszystko! W moich aplikacjach lubię dla poprawy czytelności dodać skrypt w stylu bin/myapp, który jest po prostu takim uruchomieniem index.php ale można go uruchamiać jako polecenie:
#!/usr/bin/env php <?php require __DIR__ . '/../public/index.php';
Dzięki temu polecenia można uruchamiać bardzo łatwo z katalogu głównego aplikacji:
bin/myapp user create --verbose email@example.com
Efekt będzie podobny do tego (kliknij aby powiększyć):
Informacje dla użytkownika (banner, usage)
Moduły ZF2 mają dwie funkcjonalności ułatwiające użytkownikom tworzonej aplikacji korzystanie z poleceń: banner informacyjny i instrukcje używania.
Banner informacyjny to nic innego jak wiadomość pokazywana w konsoli, gdy użytkownik nie wpisze żadnych poleceń. Moduł, który chce dodać swoją wiadomość powinien implementować interfejs Zend\ModuleManager\Feature\ConsoleBannerProviderInterface, który posiada jedną metodę: getConsoleBanner. Powinna ona zwracać string, który będzie po prostu wypisany w konsoli, np. po utworzeniu metody:
/** * @param AdapterInterface $console * @return string */ public function getConsoleBanner(AdapterInterface $console) { return '*************************************************' . PHP_EOL . '* Witaj w trybie poleceń mojej aplikacji *' . PHP_EOL . '*************************************************' . PHP_EOL; }
i wpisaniu polecenia otrzymamy efekt podobny do tego (kliknij aby powiększyć):
O ile banner wyświtlany jest przy każdym uruchomieniu polecenia w konsoli, o tyle informacje o użyciu pokazywane są tylko, gdy wpisane polecenie nie pasuje do żadnego ze znanych. Służy do poinformowania użytkownika o dostępnych poleceniach, ich formacie oraz pełnionej roli. Aby moduł mógł wyświetlać taką pomoc, musi implementować interfejs Zend\ModuleManager\Feature\ConsoleUsageProviderInterface oraz posiadać metodę getConsoleUsage. Metoda powinna zwracać string (podobnie jak w przypadku banneru) lub array. Ta druga forma daje dużo większe możliwości. Zwracana tablica może być utworzona jako klucz => wartość, gdzie klucz to format polecenia, a wartość to jego opis. Polecenia zostaną przy wyświetlaniu zebrane ze wszystkich modułów oraz odpowiednio sformatowane (szerokości). Podane tutaj polecfenia są tylko informacją dla użytkownika i nie mają wpływu na routing poleceń.
Aby uzyskać pomoc na temat polcenia z przykładu z początku wpisu można utworzyć metodę:
/** * @param AdapterInterface $console * @return array */ public function getConsoleUsage(AdapterInterface $console) { return array( 'user create [--verbose|-v] <userEmail>' => 'Tworzy konto użytkownika o podanym adresie email', ); }
Po wpisaniu polecenia otrzymamy efekt podoby do tego (kliknij aby powiększyć):