mnapoli/silly
Silly is a lightweight library for building CLI apps in PHP. It wraps Symfony Console with a simple, callback-based API, optional dependency injection support, and helpers for defining commands and arguments quickly—ideal for small tools and prototypes.
Installation:
composer require mnapoli/silly
No additional configuration is needed—just require the Silly\Silly class.
First Command:
Create a basic command class in app/Console/Commands/Hello.php:
<?php
namespace App\Console\Commands;
use Silly\Silly;
class Hello extends Silly
{
public function handle()
{
$this->line('Hello, Silly!');
}
}
Run It:
php artisan silly:run App\Console\Commands\Hello
(Note: If using Laravel, register the SillyServiceProvider in config/app.php.)
Silly\Silly (extends Symfony\Component\Console\Command).$this->line(), $this->ask(), $this->choice(), etc.class MyCommand extends Silly
{
protected $name = 'app:my-command'; // Optional: auto-detected via class name.
public function handle()
{
$this->line('Running...');
}
}
class Deploy extends Silly
{
protected $signature = 'deploy {--dry-run} {--env=production}';
protected $description = 'Deploy the app';
public function handle()
{
if ($this->option('dry-run')) {
$this->line('Dry run mode');
}
}
}
// app/Providers/SillyServiceProvider.php
namespace App\Providers;
use Silly\Silly;
use Illuminate\Support\ServiceProvider;
class SillyServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->singleton(Silly::class);
}
}
// app/Console/Kernel.php
protected $commands = [
\App\Console\Commands\Hello::class,
];
trait LoggingTrait
{
protected function log($message)
{
$this->line('[LOG] ' . $message);
}
}
class MyCommand extends Silly
{
use LoggingTrait;
public function handle()
{
$this->log('Command started');
}
}
class Backup extends Silly
{
protected $signature = 'db:backup {--path=backups}';
public function handle()
{
$path = $this->option('path');
if (!$this->confirm("Backup to {$path}? [y/N]")) {
return;
}
// Backup logic here...
$this->success('Backup complete!');
}
}
No Built-in Artisan Integration:
app/Console/Kernel.php or use a service provider.SillyServiceProvider to bind Silly commands to Laravel’s container.Signature Conflicts:
app:deploy vs. deploy:app).Output Formatting:
Output class. Overriding $output can break formatting.$this->line() instead of echo for consistent styling.Dependency Injection:
$this->line($this->app->make(MyService::class)->doSomething());
php artisan silly:run MyCommand --verbose
Silly\Events\CommandEvent for pre/post hooks:
Silly::listen(function ($event) {
$event->getCommand()->line('Event triggered!');
});
Custom Commands Directory: Override the default command discovery:
Silly::setCommandsDirectory(app_path('Console/ExtendedCommands'));
Global Options: Add reusable options via a trait:
trait GlobalOptionsTrait
{
protected function getGlobalOptions()
{
return ['--env' => Input::getOption('env')];
}
}
Interactive Prompts: Chain methods for complex UX:
$name = $this->ask('Your name');
$age = $this->ask('Your age', 30);
$this->choice('Select option', ['A', 'B', 'C'], 'A');
Silly::setColorized(true)).Silly::setColorized(true);
Silly::setColors(['error' => '<fg=red>']);
How can I help you explore Laravel packages today?