Home | All articles | Code

Fluent CLI in PHP: Creating Console Commands with __call and No Boilerplate

Php Reading time ~3 minutes
Fluent CLI in PHP: Creating Console Commands with __call and No Boilerplate

As developers, we often need to work with the command line — executing shell commands, parsing output, or automating system tasks. While many libraries exist for CLI interaction, they can sometimes feel bloated or overly complex when all you need is something lightweight and expressive.

That’s where PhpFluentConsole comes in — a simple yet flexible library designed to make command-line interaction in PHP fluent, readable, and easy to extend.

Why This Library?

PhpFluentConsole doesn’t try to replace popular CLI frameworks — it complements them. It’s great for situations where you just need to run system commands, collect their output, and maybe scan for patterns or return codes — all without diving deep into docs or verbose config.

If you've ever wanted to wrap system commands in a clean API or build your own custom tooling on top of shell commands, this is for you.

Key Features

Fluent Interface

Commands are built using a fluid, chainable syntax:

$cli = new ConsoleRunner();
$cli->setCommand('echo')
    ->addKey('Hello, World!');

Return Code Handling

Want to know if a command ran successfully?

if (!$cli->run()) {
    echo "Command failed with code: " . $cli->getReturnCode();
}

Output Matching with Regex

Looking for specific info in the output? Just match it with a pattern:

if ($cli->run()) {
    $matches = $cli->getMatches('/Error/');
    print_r($matches);
}

Simple Output Access

Grab all output lines as an array:

if ($cli->run()) {
    print_r($cli->getOutput());
}

Installation

composer require mikhailovlab/php-fluent-console

API Overview

Set the command to run

public function setCommand(string $cmd): self

Add a command argument

public function addKey(string $key): self

Sets the encoding for output. For example, '866' to display Cyrillic in Windows.

public function encoding(?string $encoding = null): self

Sets a flag that the encoding should be converted back. This method is useful for returning the output in the original encoding for working with cli.

public function decoding(): self

Returns the current command.

public function getCommand(): string

Executes the command, returns true if return code is 0

public function run(): bool

Returns the command output as an array

public function getOutput(): array

Returns the process exit code

public function getReturnCode(): int

Checks output for a regex-based error

public function hasError(string $pattern): bool

Returns output lines that match a regular expression.

public function getMatches(string|array $patterns): array

Examples

Example 1: List Docker Containers

$cli = new ConsoleRunner();
$cli->setCommand('docker')
    ->addKey('ps');

if ($cli->run()) {
    print_r($cli->getOutput());
}

Example 2: We receive a list of containers with electronic signatures

$cli = new ConsoleRunner()
     ->setCommand('csptest')
     ->addKey('-keyset')
     ->addKey('-enum_cont')
     ->addKey('-verifycontext')
     ->addKey('-fqcn');

if ($cli->run()) {
    print_r($cli->getMatches('#\\\\.*#'));
}

$pattern = '/\[ErrorCode:\s*(0x[0-9A-Fa-f]+)\]/';
print_r('Error code: ' . $cli->getMatches($pattern)[0]);

Example 3: Extending with __call Magic

Instead of calling addKey('-flag') every time, we can extend the base class and use method names that map to CLI flags:

class customRunner extends ConsoleRunner
{
    private $methods = [
        'keyset',
        'enum_cont',
        'verifycontext',
        'fqcn'
    ];

    public function __call(string $name, array $arguments): self
    {
        if (in_array($name, $this->methods)) {
            $this->addKey('-' . $name);
            if (!empty($arguments)) {
                foreach ($arguments as $arg) {
                    $this->addKey((string) $arg);
                }
            }
            return $this;
        }
        throw new \BadMethodCallException("Method $name is not supported");
    }
}

Now you can call CLI flags as methods:

try{
    $cli = new customRunner()
         ->setCommand('csptest')
         ->keyset()
         ->enum_cont() 
         ->verifycontext()
         ->fqcn();

    if ($cli->run()) {
        print_r($cli->getMatches('#\\\\.*#'));
    }

   $pattern = '/\[ErrorCode:\s*(0x[0-9A-Fa-f]+)\]/';
   print_r('Error code: ' . $cli->getMatches($pattern)[0]);

}catch (Exception $e){
    print_r($e->getMessage());
}

 

You can even move command logic into your own semantic methods:

try{
    $containers = new customRunner()
                ->getContainers();

    print_r($containers);

}catch (Exception $e){
    print_r($e->getMessage());
}

Conclusion

PhpFluentConsole is a handy, fluent tool for working with shell commands in PHP. Whether you’re parsing logs, automating dev tools, or building a higher-level CLI wrapper, this library helps keep your code clean and maintainable.

👉 Check it out on GitHub and Packagist

Feel free to drop a star, create an issue, or suggest improvements!

author
Dmitry Mikhailov
Jul 10, 2025
356

News, discussions, training

telegram
Telegram

Discussion of programming, assistance in learning

youtube
Youtube

Examples of work, training videos

Subscribe To Our Newsletter

Monthly digest of what's new and exciting from us.

© 2025 Platforms & Software. All rights reserved.

  • email
  • packagist
  • telegram
  • youtube