league/climate
League CLImate makes PHP CLI output nicer with easy colored text, formatting, and styled messages. Install via Composer and use a simple API to print red, blue, and more, helping your command-line scripts look clean and readable.
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:
use League\CLImate\CLImate;
$climate = new CLImate();
$climate->blue('Task completed!')->bold();
Where to look first: CLImate Docs → "Basic Usage" section.
Colored Output & Styling
$climate->yellow('Warning: ')->bold()->underline('Disk space low!');
$climate->error('Failed') for red).Interactive Prompts
fgets() with structured prompts:
$name = $climate->input('Enter your name:')->defaultTo('Guest');
$confirm = $climate->confirm('Proceed?', false);
$choice = $climate->radio('Select:', ['Option 1', 'Option 2']);
Progress & Feedback
$progress = $climate->progress()->start(100);
foreach ($items as $item) {
$progress->advance();
}
$spinner = $climate->spinner('Processing...');
$spinner->start();
// Simulate work
$spinner->finish();
Tables & Data Display
$climate->table(['Name', 'Status'], [
['Task 1', 'Completed'],
['Task 2', 'Pending'],
]);
Argument Parsing
$args = $climate->arguments->getArray('d'); // Parse `--d=value` flags
Artisan Commands: Inject CLImate into commands via constructor:
use League\CLImate\CLImate;
class MyCommand extends Command {
protected $climate;
public function __construct(CLImate $climate) {
$this->climate = $climate;
parent::__construct();
}
public function handle() {
$this->climate->info('Command executed!');
}
}
Register the service provider in config/app.php:
'providers' => [
// ...
League\CLImate\CLImateServiceProvider::class,
],
Console Kernel:
Use CLImate globally in app/Console/Kernel.php:
protected $climate;
public function __construct(CLImate $climate) {
$this->climate = $climate;
}
public function handle() {
$this->climate->comment('Starting console tasks...');
}
Views & Blade:
Extend CLImate for Blade templates (e.g., resources/views/console.blade.php):
@inject('climate', 'League\CLImate\CLImate')
{{ $climate->table(['Key', 'Value'], $data) }}
ANSI Escape Sequences
forceAnsiOn():
$climate->forceAnsiOn();
$climate->supportsAnsi() before rendering.Progress Bar Precision
99.999%).precision() method:
$progress->precision(0); // Show whole numbers only
Input Validation
accept() method may not work as expected with multiline input.defaultTo() with validation:
$input = $climate->input('Enter value:')->defaultTo('default')->accept(fn($val) => strlen($val) > 3);
Terminal Width Detection
$climate->width().Phar/Non-CLI Contexts
STDOUT errors in non-CLI environments (e.g., web servers).if (php_sapi_name() === 'cli').$climate->forceAnsiOff();
buffer() to capture output for debugging:
$buffer = $climate->buffer();
$buffer->write($climate->red('Test'));
$output = $buffer->output();
php -l or use phpstan to catch deprecated methods (e.g., valueArray() → values()).Custom Output Writers
$climate->output = new \League\CLImate\Util\Writer\FileWriter('log.txt');
Extend CLImate
extend():
$climate->extend(function ($climate) {
$climate->success('Custom method!', fn() => $climate->green('Success!'));
});
PSR-3 Logger Integration
$logger = new \League\CLImate\Logger\Logger($climate);
$logger->info('Log message');
Art & Animations
$climate->art(__DIR__.'/assets/art.txt');
$climate->animate('http://example.com/loading.gif');
string return types; ensure IDE autocompletion is enabled (e.g., PHPStorm’s "Strict Generics").ext-mbstring or symfony/polyfill-mbstring for Unicode support.seld/cli-prompt polyfill if password input fails (included in v3.1.1+).forceRedraw() in tight loops; use each() for batch updates.
```markdown
### Laravel-Specific Gotchas
1. **Service Container Binding**
- Bind CLImate as a singleton in `AppServiceProvider`:
```php
$this->app->singleton(CLImate::class, function () {
return new CLImate();
});
```
- *Why*: Prevents recreation of CLImate instances (e.g., in loops).
2. **Artisan Command Output**
- Use `$this->climate` instead of `$this->output` in commands to avoid Artisan’s default styling conflicts.
3. **Testing CLI Output**
- Mock CLImate in tests:
```php
$mock = Mockery::mock(CLImate::class);
$mock->shouldReceive('info')->once()->with('Test');
$this->app->instance(CLImate::class, $mock);
```
4. **Queue Workers**
- Avoid CLImate in queue workers (non-CLI context). Use logging instead:
```php
if (app()->runningInConsole()) {
$climate->info('Processed job!');
} else {
Log::info('Processed job!');
}
```
How can I help you explore Laravel packages today?