swew / cli
SWEW/CLI: A PHP package for streamlined command line interface (CLI) development, providing an intuitive API for creating custom commands, handling input/output, and executing command logic effortlessly. Simplify your CLI application development with rapid development.
Requires
- php: >=8.1
Requires (Dev)
- laravel/pint: 1.9.0
- phpstan/phpstan: ^1.10.53
- psalm/phar: ^5.18.0
- swew/dd: ^1.3.1
- swew/test.phar: ^1.5.13
README
The package is a PHP library for building console applications and commands in an object-oriented manner. It provides a simple and intuitive API for defining commands and handling arguments and options. It also includes utilities for interacting with the console, such as coloring output and prompting for user input. With this package, you can quickly create powerful command-line tools and automate repetitive tasks in your development workflow.
Packages developed by SWEW
- swew/cli - A command-line interface program with formatting and text entry functions.
- swew/test - A test framework that is designed to fix the fatal flaw of other test frameworks.
- swew/db - A lightweight, fast, and secure PHP library for interacting with databases, creating migrations, and running queries.
- swew/dd - The simplest way to debug variables. As in Laravel.
Install
composer require swew/cli
Example of use
Create command
<?php namespace My\Cli\Commands; use Swew\Cli\Command; class ShowTimeCommand extends Command { const NAME = 'show:time {prefix}'; const DESCRIPTION = 'The function shows the current time.'; public function __invoke(): int { $prefix = $this->arg('prefix')->getValue(); $time = $prefix . ' ' . date('H:i:s'); $this->output->writeLn($time); return self::SUCCESS; } }
Create cli-program
<?php namespace My\Cli; use Swew\Cli\SwewCommander; use My\Cli\Commands\ShowTimeCommand; class MySuperCli extends SwewCommander { protected array $commands = [ ShowTimeCommand::class, ]; }
Run cli-program
<?php // index.php require __DIR__.'/vendor/autoload.php'; use My\Cli\MySuperCli; (new MySuperCli($argv))->run();
php index.php 'show:time at'
API / DOC
Console — User Commands
An example of creating a command with SWEW-CLI.
The command must be inherited from the Swew\Cli\Command
class and the class must be callable via the __invoke
method.
The class must also have two obligatory constants.
NAME
- necessary to call the command, it can also contain arguments.- The
DESCRIPTION
is a description of the command and is used to call thehelp
message.
As a result of the execution of the command should return the result - the status code. If all was successful, it is 0
.
class SendEmail extends Command { const NAME = 'send:email'; const DESCRIPTION = 'Command to send email'; public function __invoke(): int { // ... return self::SUCCESS; } }
By inheriting from the class Command
- we also get auxiliary methods defined in it.
init(): void
- will be run before execution (can be overridden)arg(string $key):
CommandArgument` - getting the argument passed to the commandargv(string $key): mixed
- get valuegetHelpMessage(): string
- get help message for the command (can be overridden)isValid(): bool
- check if all required arguments are passed to the command correctlygetErrorMessage():string
- Get an error messagecall(string $command, ?array $args:) int
- call another command
Working with command parameters, description of arguments
// Only command name, no arguments const NAME = 'send:email'; // One required argument userId, the argument is always wrapped in curly braces const NAME = 'send:email {--userId}'; // Optional argument userId is empty string const NAME = 'send:email {--userId=}'; // Optional argument with default value is string const NAME = 'send:email {--userId=1}'; // Optional argument, userId as array const NAME = 'send:email {--userId=[]}'; /** Typing */ // Argument with typing const NAME = 'send:email {--userId (int)}'; // Argument with typing const NAME = 'send:email {--userId (float)}'; // Argument with typing, default userId === 0 const NAME = 'send:email {--userId= (int)}'; // Argument with typing, default userId === '' const NAME = 'send:email {--userId= (str)}'; // Argument with typing, default userId === false const NAME = 'send:email {--userId= (bool)}'; // Argument with typing, default: userId === false // if command: `send:email` userId === true // if command: `send:email --userId` userId === true const NAME = 'send:email {--userId= (bool)}'; // Alias for argument const NAME = 'send:email {-S|--silent}'; /** Description */ const NAME = 'send:email {mail : The description, will be reflected in help}'; /** Example command with one argument in the full description */ const NAME = 'send:email {--count|-C=1 (int) : Count of mails}'; // command | argument|alias|default | type | description
Writing Output
write / writeLn / info / warn / error
$this->output->write('Hello '); $this->output->write('world', '<b>%s <br></>'); // formatting $this->output->writeLn('Hello'); // write with new line $this->output->writeLn('world', '<b>%s <br></>'); $this->output->info('Some good news'); $this->output->warn('A little attention'); $this->output->error('Something has gone wrong'); $this->output->clear(); // Reset terminal window
Width / Height
$this->output->width(); $this->output->height();
Formatting
$this->output->write('<b><black><bgRed>Hello world</>'); // OR $format = '<b><black><bgRed>%s</>'; $this->output->write('Hello world', $format);
Symbols
</>
- escape<br>
- new line<b>
- bold<u>
- underline
Colors
Cursors
<saveCursor>
<restoreCursor>
<eraseToEndLine>
<eraseToStartLine>
<eraseLine>
<eraseToBottom>
<eraseToTop>
Without formatting
If you do not want to use formatting, specify this
$this->output->setAnsi(false);
Clear bash colors
Remove bash color symbols from string
$this->output->clearColor($text); // no color string
Empty lines
// Write a single blank line... $this->output->newLine(); // Write three blank lines... $this->output->newLine(3);
Link
$this->output->getLink($url, $text);
Prompting For Input
ask
public function __invoke(): int { $name = $this->output->ask('What is your name?'); // ... return self::SUCCESS; }
askYesNo
public function __invoke(): int { $name = $this->output->askYesNo('Is this the best CLI utility?', true); // ... return self::SUCCESS; }
secret
public function __invoke(): int { $password = $this->output->secret('What is the password?'); // ... return self::SUCCESS; }
Choice Question
public function __invoke(): int { /** @var string */ $answer = $this->output->choice( 'What is your name?', ['Leo', 'Mike', 'Don', 'Raph'], $isRequired = true // optional ); $this->output->writeLn($answer); // ... return self::SUCCESS; }
Choice Multiple
public function __invoke(): int { /** @var array */ $answer = $this->output->select( 'What is your name?', ['Leo', 'Mike', 'Don', 'Raph'], $selectedIndex = [], // optional $isRequired = true, // optional $isMultiple = true, // optional ); // ... return self::SUCCESS; }
Tables
$title = ['Name', 'Age', 'Weapon']; $list = [ ['Leo', 22, 'Swords'], ['Mike', 21.6, 'Nunchaks'], ['Don', 21.9, 'Bo'], ['Raphael', 21.5, 'Saii'], ]; $this->output->table($title, $list);
Progress bar
$bar = $this->output->createProgressBar(count($users)); $bar->start(); // show progress bar foreach ($users as $user) { $this->someTask($user); $bar->increment(); // progress } $bar->finish(); // remove progressbar
Output
If you only need output to the console, you can use the Output
class separately.
<?php require __DIR__ . '/../vendor/autoload.php'; use Swew\Cli\Terminal\Output; $output = new Output(); $output->writeLn('Hello world!');