beecubu/php-foundation-cli

Simple CLI Framework based on PHP Object Foundation.

Maintainers

Package info

bitbucket.org/beecubu/php-foundation-cli

pkg:composer/beecubu/php-foundation-cli

Statistics

Installs: 100

Dependents: 1

Suggesters: 0

v1.6.1 2026-03-12 02:16 UTC

This package is auto-updated.

Last update: 2026-03-12 02:16:49 UTC


README

Simple CLI framework based on PHP Object Foundation. It provides:

  • Console utilities for colored output, input helpers, progress UI, and simple charts.
  • A tiny Application + ViewController stack to build CLI screens/flows.

Requirements

  • PHP 7.1+
  • beecubu/php-foundation-helpers (Composer dependency)
  • Optional: ext-readline for nicer input handling

Installation

composer require beecubu/php-foundation-cli

Quick Start

<?php

use Beecubu\Foundation\Cli\Console;

Console::title('My CLI App');
Console::line('Hello <green>world</green>!');

Colors

Colors are expressed with simple tags:

<red>text</red>, <green>text</green>, <cyan>text</cyan>, <yellow>text</yellow>, <purple>text</purple>

Background tags:

<b_red>text</b_red>, <b_green>text</b_green>, <b_blue>text</b_blue>, ...

Console Helpers

Output

Console::line('A single line');
Console::lines(['Line 1', 'Line 2']);
Console::title("Main Title\nSubtitle");
Console::section("Section Title");
Console::center('Centered text');
Console::separator();
Console::table([
    ['Name' => 'Ada', 'Age' => 31],
    ['Name' => 'Linus', 'Age' => 54],
], [
    'align' => ['Age' => 'right'],
    'headerColor' => 'brown',
    'width' => [
        'mode' => 'auto',
    ],
]);
Console::error('Something went wrong', true);
Console::success('All good');
Console::warning('Be careful');
Console::clear();

ASCII Tables

$rows = [
    ['Name' => 'Ada', 'Role' => 'Engineer', 'Score' => 98.5],
    ['Name' => 'Linus', 'Role' => 'Architect', 'Score' => 87],
    ['Name' => 'Grace', 'Role' => 'Scientist', 'Score' => 91.25],
];

Console::table($rows, [
    'align' => [
        'Name' => 'left',
        'Role' => 'left',
        'Score' => 'right',
    ],
    'headerColor' => 'brown',
    'width' => [
        'mode' => 'max',
        'size' => 60,
    ],
    'separators' => [
        'header' => true,
        'rows' => true,
    ],
]);

Available options:

Console::table($rows, [
    'align' => [
        'Name' => 'left',
        'Role' => 'center',
        'Score' => 'right',
    ],
    'headerColor' => 'brown',
    'width' => [
        'mode' => 'auto', // auto|min|max
        'size' => 100,    // only used when mode is min or max
    ],
    'separators' => [
        'header' => true,
        'rows' => true,
    ],
]);
  • align: alignment per column. Allowed values are left, right, and center.
  • headerColor: header text color. Uses the same color names supported by Console::line(). Default is white.
  • width.mode:
    • auto: natural table width based on content.
    • min: expands the table up to the given width if there is free space.
    • max: limits the table to the given width and wraps cell content when needed.
    • fixed: forces the table to exactly the given width (expands if smaller, wraps if larger).
  • width.size: target total table width in characters.
  • separators.header: enables or disables the header separator. Default is true.
  • separators.rows: enables or disables separators between rows. Default is true.

Notes:

  • Input rows should be associative arrays.
  • Column order is discovered from the first time each key appears.
  • Missing values in later rows are rendered as empty cells.
  • Header alignment follows the alignment configured for each column.
  • In width.mode = max, long cell content is wrapped to multiple lines automatically.

Input

$name = Console::getString('Your name', false);
$age = Console::getIntValue('Age', 1, 120);
$price = Console::getValue('Price', 0, 9999, true, 9.99);
$ok = Console::getYesNo('Continue?');
$date = Console::getDate('Pick a date');
$dateTime = Console::getDateTime('Pick a date and time');

Interactive Menu

Console::menu() shows an interactive menu where the user navigates with the arrow keys and confirms with Enter. Requires a real TTY (does not work with piped input).

$index = Console::menu('Which environment?', [
    'Production',
    'Staging',
    'Local',
]);

With options:

$index = Console::menu('Action:', ['Create', 'Edit', 'Delete'], [
    'activeColor' => 'green',   // color of the selected option (default: cyan)
    'marker'      => '→',       // marker character (default: ▶)
    'default'     => 1,         // initially selected index (default: 0)
]);
  • Returns the zero-based index of the selected option.
  • Arrow up/down cycles through options (wraps around).
  • The terminal is left in its original state after selection.
  • Works on Unix/macOS. Not supported on Windows.

Options

// Returns array with exactly one true
$options = Console::getOption('Choose', 'a', 'b', 'c');

// Returns index (0-based)
$index = Console::getOptionIndex('Choose', 'a', 'b', 'c');

Progress UI

// Progress bar
Console::progressbar(100, true, 'Starting');
Console::progressbar(10, false, 'Working...');
Console::progressbar(90, false, 'Done');

// Spinner (call repeatedly in a loop)
Console::spinner('Loading...', 3);
Console::spinner(false); // clear

Simple Charts

$data = [
    ['value' => 0.25, 'color' => 'red'],
    ['value' => 0.35, 'color' => 'green'],
    ['value' => 0.40, 'color' => 'blue'],
];

Console::printChartPercentageBar($data);

Application + ViewController

This is a small view stack to build multi-screen CLI apps.

<?php

use Beecubu\Foundation\Cli\Application\Application;
use Beecubu\Foundation\Cli\Application\ViewController;
use Beecubu\Foundation\Cli\Console;

class MainView extends ViewController
{
    private $done = false;

    public function view(): void
    {
        Console::title('Main View');
        $name = Console::getString('Your name', false);
        Console::success("Hello $name");
        $this->done = true;
    }

    public function finished(): bool
    {
        return $this->done;
    }
}

new Application(new MainView());

Navigation

Inside any ViewController you can:

  • $this->application->pushView($anotherView) to open a new view.
  • $this->application->back() to return to the previous view.
  • $this->application->home() to return to the first view.

When a view reports finished() === true, the application will go back automatically (or exit if it was the only view).