Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Console Tools Laravel Package

zetacomponents/console-tools

A PHP library from Apache Zeta Components for building command-line applications, with argument parsing, console input/output, progress bars, tables, menus, dialogs, and reusable components for interactive terminal tools.

View on GitHub
Deep Wiki
Context7

Getting Started

What it is. zetacomponents/console-tools is the console component of Zeta Components (the old eZ Components library). It is a PHP 5-era toolbox, not a framework — you get six independent widgets:

  • ezcConsoleInput — option/argument parsing (short + long options, types, validators, dependencies)
  • ezcConsoleOutput — tagged, colored, verbosity-aware output (<error>…</error>)
  • ezcConsoleProgressbar, ezcConsoleProgressMonitor, ezcConsoleStatusbar — progress feedback
  • ezcConsoleTable — column-aligned tables
  • ezcConsoleQuestionDialog, ezcConsoleMenuDialog — interactive prompts

There is no facade, no service provider, no config file. You new a class and use it.

Install.

composer require zetacomponents/console-tools

This pulls zetacomponents/base, whose ezc_bootstrap.php registers the ezc class autoloader. That autoloader is not PSR-4, so if new ezcConsoleOutput() reports "class not found", the base package (or the bootstrap include) is missing — not the console package. Non-Composer installs must require Base/src/ezc_bootstrap.php themselves.

Where to look first. src/input.php and src/output.php are the two files you will use in every script. After those, read the per-widget files (progressbar.php, table.php, question_dialog.php); each class has a plain-English docblock example at the top, and the docs/ folder ships a tutorial per component. Options are separate classes in src/options/ — that is where you look when you need to change a default.

First use case. A one-file CLI script: two options, colored output, and a progress bar.

<?php
require __DIR__ . '/vendor/autoload.php';

$output = new ezcConsoleOutput();
$output->formats->info->color = 'green';
$output->formats->warn->color = 'yellow';

$input = new ezcConsoleInput();

$help = new ezcConsoleOption('h', 'help', ezcConsoleInput::TYPE_NONE, false, 'Show help');
$input->registerOption($help);

$file = new ezcConsoleOption('f', 'file', ezcConsoleInput::TYPE_STRING, 'data.csv', 'File to import');
$input->registerOption($file);

try {
    $input->process();               // parses $_SERVER['argv']
} catch (ezcConsoleInputException $e) {
    $output->outputLine('<error>' . $e->getMessage() . '</error>');
    exit(1);
}

if ($help->value) {
    echo $input->getHelp();          // or render usage from $input->options
    exit(0);
}

$output->outputLine("<info>Importing {$file->value}</info>");

$bar = new ezcConsoleProgressbar($output, 100);
$bar->start();
foreach (range(1, 100) as $i) {
    $bar->advance();
}
$bar->finish();

That skeleton — options → validate → output → widget — is the shape of every script built on this package.

Implementation Patterns

One bootstrap per command, options declared declaratively. Register every option up front in a single method, then let process() do the parsing. Do not hand-roll $argv parsing alongside it; ezcConsoleInput already handles --opt=value, --opt value, -abc bundling and type coercion.

$verbose = new ezcConsoleOption('v', 'verbose', ezcConsoleInput::TYPE_NONE);
$verbose->multiple = true;               // repeatable: -vvv
$input->registerOption($verbose);

$output->options->verbosityLevel = max(1, (int) count($verbose->value));

Cross-option rules belong in the option, not in if soup. Options support dependencies and value validators, both enforced by process():

$format = new ezcConsoleOption('F', 'format', ezcConsoleInput::TYPE_STRING);
$format->addValidator(function ($value) {
    return in_array($value, ['csv', 'json'], true);
});
$input->registerOption($format);

$json = new ezcConsoleOption('', 'json', ezcConsoleInput::TYPE_NONE);
$json->dependencies[] = new ezcConsoleOptionRule($format, ['json']);
$input->registerOption($json);

Invalid combinations then throw ezcConsoleInputException with a usable message instead of producing silently wrong behaviour.

Define semantic output formats once, then use tags everywhere. Pick names like error, warn, info, debug in a configureOutput() helper, and write user-facing strings as tagged text. This gives you one place to disable colorization (piped output, CI) and one place to add verbosity gating:

$output->formats->debug->color = 'gray';
// only actually printed when verbosity allows it
$output->outputLine('<debug>cache hit for ' . $key . '</debug>');

Use the right progress widget. ezcConsoleProgressbar for one loop with a known total, ezcConsoleProgressMonitor for a short list of named tasks with per-task status, ezcConsoleStatusbar for many tiny items. In all three cases wrap the loop in try/finally and call finish() — otherwise a thrown exception leaves the cursor mid-bar and the next line of output is mangled.

Tables: build rows by array access, print once.

$table = new ezcConsoleTable($output, 100);
$table[] = ['ID', 'Name', 'Status'];
foreach ($rows as $row) {
    $table[] = [(string) $row->id, $row->name, '<info>ok</info>'];
}
$table->outputTable();

Set $table->options->colWidth and the wrap behaviour explicitly if your data can contain long unbroken strings — the auto layout is easy to blow past the terminal width.

Interactive prompts. Use ezcConsoleQuestionDialog for free-form/yes-no answers and ezcConsoleMenuDialog (associative array of key => label) for menus. ezcConsoleQuestionDialogMapping is the convenient way to map y/n/yes/no onto booleans. Always give the dialog a default and always give the script a --yes/--no-interaction escape hatch.

Testing. process() accepts an array of arguments, so option parsing is unit-testable without shelling out:

$input = $this->buildInput();
$input->process(['script.php', '--file', 'x.csv', '-vv']);
$this->assertSame('x.csv', $input->getOption('file')->value);

Widgets that write to stdout can be wrapped in output buffering; interactive dialogs generally cannot be tested this way, so keep them behind a thin method you can stub.

In a Laravel codebase. Treat this as a library for standalone scripts (bin/, deploy scripts, importers) rather than as an Artisan replacement. Inside a command, Laravel already gives you $this->output (Symfony Console) with formatting, tables and progress bars; the two output systems do not share a stream, and you cannot hand a Symfony OutputInterface to an ezc widget. If you must mix them, isolate the ezc code in one method and flush/detach before returning to Laravel output. Given zero dependents and low activity, do not adopt it for new application code — it is a reasonable choice only when you are already in a Zeta/eZ codebase or want a dependency-free set of widgets pinned to a legacy PHP version.

Gotchas and Tips

  • Maintenance status is the headline risk. Zeta Components is archived (the project was retired years ago) and the package's GitHub license metadata reports NOASSERTION. The source headers carry Apache-2.0, but confirm that from the files themselves before shipping — do not rely on the repo badge.
  • PHP 8 compatibility is not guaranteed. This is a PHP 5-era codebase; expect each(), ${} interpolation, bare-word constants, and dynamic-property deprecations to bite on modern runtimes. Test on your actual PHP version before committing, and be prepared to pin an older PHP or vendor a patched fork. This is the single biggest reason to prefer Symfony Console for greenfield work.
  • The ezc autoloader is invisible to tooling. No PSR-4 means IDEs, PHPStan and Laravel's package discovery will not resolve these classes until vendor/autoload.php has pulled in ezc_bootstrap.php. Static analysis will be mostly useless; rely on the docblocks in src/.
  • Uncaught parse exceptions look like crashes. process() throws ezcConsoleInputException for bad types, failed validators and unmet dependencies. Always wrap it, print the message, and exit non-zero — a stack trace is not a user-facing error message. Also check a registered help option's value yourself rather than assuming it exits for you.
  • Format tags eat arbitrary text. <error> in a filename, a database value or an exception message will be interpreted as a format tag. Sanitize untrusted strings before outputLine()/outputText() — strip or neutralize </>. This is the most common silent-data-loss bug with this package.
  • Colorization must be off for non-TTY output. $output->options->colorization controls it; leaving it on pollutes logs, CI output and anything piped to a file with escape sequences. Drive it from your own --no-color flag or from stream_isatty(STDOUT).
  • Progress bars and other output do not mix. The bar redraws in place with \r; any outputLine() or var_dump() inside the loop destroys the line. Finish the bar first. Also note the redraw frequency is time-based (roughly a few per second), so a very fast loop appears to jump from 0% to 100% — lower it if you need deterministic output in tests or logs.
  • Dialogs hang forever when STDIN is not a terminal. Cron jobs, CI and Docker without -i will block indefinitely. Guard on TTY detection or require an explicit --yes.
  • Validation is type-only by default. TYPE_INT does not check ranges or signs. Anything domain-specific needs an explicit validator — which is also the cleanest extension point in the whole package, since validators are plain callables.
  • Extension points are limited but sufficient. Mutate ezcConsoleOutputFormat objects for new styles, register callables as option validators, subclass the widgets if you need custom rendering. There is no plugin system; don't go looking for one.
  • Debugging parsed state: iterate the registered options and dump each ->value along with $input->arguments for positional parameters. Nine times out of ten a "broken" script is an option whose type was left at TYPE_NONE while the user passed a value.
  • Terminal width detection is best-effort (environment variables and stty, degrading on Windows). For tables and progress bars, set widths explicitly in code rather than trusting detection, especially in containers where COLUMNS is unset.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core