afeefa/cli-app¶
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
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