league/climate
League CLImate makes PHP CLI output nicer with easy colored text, formatting, and styled messages. Install via Composer and use simple methods like red() or blue() to print readable, attention-grabbing console output for scripts and command-line tools.
Installation:
composer require league/climate
Add to composer.json under require-dev if only for local scripts.
First Use Case:
Replace raw echo statements in CLI scripts with CLImate for colored output:
$climate = new \League\CLImate\CLImate;
$climate->success('Migration completed!')->bold();
Key Entry Points:
$climate->text(), $climate->error(), $climate->warning().$climate->input(), $climate->confirm(), $climate->checkboxes().$climate->table(), $climate->progress().$climate->debug() (logs to STDERR).Where to Look First:
src/League/CLImate/ for core classes (e.g., CLImate.php, TerminalObject/).Artisan::output() with CLImate’s Logger for consistency.Pattern: Replace echo/Artisan::line() with CLImate in commands.
Example:
use League\CLImate\CLImate;
use Symfony\Component\Console\Command\Command;
class DeployCommand extends Command {
protected function execute(InputInterface $input, OutputInterface $output) {
$climate = new CLImate();
$climate->info('Starting deployment...')->bold();
// Progress bar for steps
$progress = $climate->progress()->start('Deploying...');
foreach ($steps as $step) {
$progress->advance();
$climate->text(" - $step");
}
$progress->finish();
$climate->success('Deployment complete!')->newline(2);
}
}
Pattern: Replace readline() or custom input with CLImate’s prompts.
Example:
$climate = new CLImate;
// Confirmation
if ($climate->confirm('Overwrite existing files?', false)) {
$climate->text('Proceeding...')->bold();
}
// Multi-select
$options = ['Option 1', 'Option 2', 'Option 3'];
$selected = $climate->checkboxes('Choose options:', $options, 1);
$climate->text('Selected: ' . implode(', ', $selected));
// Password input (secure)
$password = $climate->password('Enter password:');
Pattern: Use tables for CLI reports or logs. Example:
$data = [
['ID', 'Name', 'Status'],
[1, 'User 1', 'Active'],
[2, 'User 2', 'Inactive'],
];
$climate->table($data)
->setHeaders(['ID', 'Name', 'Status'])
->setPadding(2)
->render();
Pattern: Wrap long-running tasks with progress bars/spinners. Example:
$climate = new CLImate;
$progress = $climate->progress()->start('Processing 100 items...');
// Simulate work
foreach (range(1, 100) as $i) {
usleep(50000);
$progress->advance("Item $i/100");
}
$progress->finish();
Pattern: Create custom decorators or extend core functionality. Example:
$climate = new CLImate;
$climate->extend('git', function ($message) {
return $this->yellow("GIT: $message");
});
// Usage:
$climate->git('Commit pushed!');
Pattern: Use CLImate as a PSR-3 logger for CLI tools. Example:
use League\CLImate\Logger;
$logger = new Logger(new CLImate());
$logger->debug('Debug message');
$logger->error('Error occurred!', ['trace' => $e->getTraceAsString()]);
Pattern: Handle Windows/Linux/macOS inconsistencies gracefully. Example:
$climate = new CLImate;
if (!$climate->isWindows()) {
$climate->text('This runs only on Unix-like systems.')->warning();
}
ANSI Color Issues:
$climate->forceAnsiOn() or check $climate->supportsAnsi() before coloring.$climate->isWindows() and adjust output accordingly.Progress Bar Precision:
$progress->setPrecision(2) or cast values to integers.Input Validation:
$climate->input() may not validate types (e.g., expects int but gets string).filter_var() or custom validation after input:
$age = (int) $climate->input('Enter age:', 0);
Terminal Width Detection:
$climate->width() may return 0 on some Windows setups.80):
$width = max($climate->width(), 80);
Multibyte Strings:
mbstring extension is enabled or use the symfony/polyfill-mbstring package.Spinner Indeterminacy:
$spinner->setInterval(100) to control refresh rate.Argument Parsing:
$climate->arguments may not handle nested options (e.g., --option=value).$climate->arguments->getArray('option') for complex cases.Output Buffering:
$climate->output()->flush().Check ANSI Support:
$climate->text('ANSI Supported: ' . ($climate->supportsAnsi() ? 'Yes' : 'No'));
Inspect Terminal Width:
$climate->text("Terminal Width: {$climate->width()} chars");
Log Raw Output:
$climate->debug('Raw output:', ['output' => $climate->output()->getContent()]);
Disable Colors for Testing:
$climate->forceAnsiOff();
Validate Input:
$input = $climate->input('Enter a number:', 0);
if (!is_numeric($input)) {
$climate->error('Invalid input!')->newline();
exit(1);
}
Custom Output Writers:
$climate->output() to redirect output to files, APIs, or databases.$climate->output(new \League\CLImate\Output\FileWriter('log.txt'));
Decorators:
\League\CLImate\Decorator\DecoratorInterface to add custom formatting (e.g., emojis, icons).$climate->extend('emoji', function ($text) {
return $this->green("🚀 $text");
});
Argument Parsers:
\League\CLImate\Argument\ArgumentParser for custom CLI argument handling.Interactive Prompts:
\League\CLImate\Prompt\Prompt to create custom prompts (e.g., select(), slider()).Progress Bar Styling:
\League\CLImate\ProgressBar\ProgressBar to change bar characters or colors.Artisan::output() with CLImate’s Logger for consistent output:
$logger = new Logger(new CLImate());
Artisan
How can I help you explore Laravel packages today?