afeefa / cli-app
Convenient wrapper around symfony console
Installs: 2 288
Dependents: 1
Suggesters: 0
Security: 0
Stars: 0
Watchers: 2
Forks: 0
Open Issues: 0
Requires
- php: >=7.4
- afeefa/debug-dump-log: ^0
- symfony/console: ^v5.4 || ^v6.1
- symfony/filesystem: ^v5.4 || ^v6.1
- symfony/process: ^v5.4 || ^v6.1
- twig/twig: ^v3.4
- wujunze/php-cli-color: ^v2.4
README
Create a symfony/console
PHP cli app with a minimum of configuration.
Description
At times a project might need a cli tool to perform some configuration, installation or maintenance work. It shouldn't be much effort to get one running. This package is a convenience wrapper around the PHP's symfony/console framework and aims to simplify the creation of cli apps. It provides:
- a fluent interface to create (nested) commands
- selectable (sub) commands and command arguments
- reusable actions
- helper functions for input, output and process execution
Installation
Install via composer as usual. Most probably you use the cli for dev purposes:
composer require afeefa/cli-app --save-dev
Documentation
See the examples below for inspiration and head over to the documentation pages:
- Read the Docs on installation, configuration and usage
- the API Documentation
Examples
Example 1: Basic workflow
The most basic example shows the workflow of cli-app
. You create one or more commands (usually in a separate file) and add those commands to the application instance by providing a command name and a description.
File: pets.php
<?php require_once __DIR__ . '/../../vendor/autoload.php'; use Afeefa\Component\Cli\Cli; use Afeefa\Component\Cli\Command; class Cats extends Command { protected function executeCommand() { $this->printList(['Kitty', 'Tiger', 'Meow']); } } class Dogs extends Command { protected function executeCommand() { $this->printList(['Laika', 'Lassie', 'Goofy']); } } (new Cli('Pets App')) ->command('cats', Cats::class, 'Show cats') ->command('dogs', Dogs::class, 'Show dogs') ->run();
Run the example:
git clone git@github.com:afeefacode/cli-app.git cd cli-app composer install examples/pets/pets # examples/pets/pets cats
Example 2: Command Actions
The examples shows three things:
- an action, which is kind of a lightweight command, that can be called from any command or action
- a prompt, which lets the user select from a list of choices
- and a possibility to reuse a command by giving it a mode
<?php ... use Afeefa\Component\Cli\Action; class Names extends Action { protected function executeAction() { $pet = $this->getArgument('pet'); $names = $pet === 'cat' ? ['Kitty', 'Tiger', 'Meow'] : ['Laika', 'Lassie', 'Goofy']; return $this->printChoice("Select a $pet", $names); // prompt } } class Feed extends Command { protected function executeCommand() { $pet = $this->getCommandMode(); $name = $this->runAction(Names::class, ['pet' => $pet]); $this->printBullet("Feed <info>$name</info>"); } } class Cuddle extends Command { protected function executeCommand() { $name = $this->runAction(Names::class, ['pet' => 'cat']); $this->printBullet("Cuddle <info>$name</info>"); } } (new Cli('Pets App')) ->command('feed-cat', [Feed::class, 'cat'], 'Feed a cat') // 'cat' = mode ->command('feed-dog', [Feed::class, 'dog'], 'Feed a dog') ->command('cuddle-cat', Cuddle::class, 'Cuddle a cat') ->run();
Run the example:
git clone git@github.com:afeefacode/cli-app.git cd cli-app composer install examples/feed/feed # examples/feed/feed feed-dog # examples/feed/feed cuddle-cat
Example 3: Command Arguments
Command arguments are a basic cli feature. If you want to help the user by providing a list of argument values to choose from, you can use selectable arguments. The example shows:
- using and consuming selectable arguments
- setting a default command
<?php ... use Afeefa\Component\Cli\SelectableArgument; class Walk extends Command { protected function setArguments() { $this->addSelectableArgument( // selectable argument 'pet', ['cat', 'dog'], 'The pet to walk with' ); $this->addSelectableArgument( // dependent argument 'name', function (SelectableArgument $argument) { $pet = $this->getArgument('pet'); $argument->choices = $pet === 'cat' ? ['Kitty', 'Tiger', 'Meow'] : ['Laika', 'Lassie', 'Goofy']; $argument->description = 'The name of the ' . $pet; } ); } protected function executeCommand() { $pet = $this->getArgument('pet'); $name = $this->getArgument('name'); if ($pet === 'cat') { $this->printBullet("<info>$name</info> does not walk with you"); } else { $this->printBullet("<info>$name</info> is happy to walk with you"); } } } (new Cli('Pets App')) ->command('walk', Walk::class, 'Walk with a pet') ->default('walk') ->run();
Run the example:
git clone git@github.com:afeefacode/cli-app.git cd cli-app composer install examples/walk/walk # examples/walk/walk # examples/walk/walk walk dog # examples/walk/walk walk dog Laika
Example 4: Nested Commands
The example shows:
- the configuration of nested commands
- the ability to inspect a commands or a command parent's name.
<?php ... use Afeefa\Component\Cli\Definitions\GroupDefinition as Group; class Play extends Command { protected function executeCommand() { $action = $this->getLocalName(); $pet = $this->getLocalParentName(); if ($pet === 'cat') { $this->printBullet("<info>Cat</info> does not like <info>$action</info>"); } else { $this->printBullet("<info>Dog</info> likes <info>$action</info>"); } } } (new Cli('Pets App')) ->group('cat', 'Play with cat', function (Group $group) { $group->command('hide-seek', Play::class, 'Hide and seek'); }) ->group('dog', 'Play with dog', function (Group $group) { $group ->command('fetch', Play::class, 'Fetch the stick') ->command('cuddle', Play::class, 'Cuddle the dog'); }) ->run();
Run the example:
git clone git@github.com:afeefacode/cli-app.git cd cli-app composer install examples/play/play # examples/play/play # examples/play/play dog # examples/play/play dog:fetch