Weave Code
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

Silly Laravel Package

mnapoli/silly

Silly is a lightweight CLI micro-framework built on Symfony Console. Define commands with simple signatures and PHP callables, get options/arguments parsing, helpers, and DI integration (PHP-DI or Pimple) while staying compatible with Symfony Console apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require mnapoli/silly
    

    For PHP-DI integration (recommended for Laravel projects):

    composer require mnapoli/silly-php-di
    
  2. Basic CLI Setup: Create a file (e.g., artisan.php) with:

    use Silly\Application;
    
    $app = new Application();
    $app->command('greet [name]', function ($name) {
        echo "Hello, {$name ?: 'World'}!\n";
    });
    $app->run();
    
  3. First Use Case: Run the command:

    php artisan.php greet John
    

    Output: Hello, John!

Where to Look First


Implementation Patterns

Laravel Integration Workflow

  1. Service Provider Setup: Register Silly in AppServiceProvider:

    use Silly\Application;
    use Silly\Bridge\Laravel\SillyServiceProvider;
    
    public function register()
    {
        $this->app->singleton('silly', function ($app) {
            $silly = new Application();
            $silly->useContainer($app); // Laravel's container is PSR-11 compliant
            return $silly;
        });
    }
    
  2. Command Registration: Define commands in a dedicated class (e.g., app/Console/SillyCommands.php):

    $silly = app('silly');
    $silly->command('user:create [name]', function ($name, \Psr\Log\LoggerInterface $logger) {
        $logger->info("Creating user: {$name}");
        // Logic here
    });
    
  3. Artisan Integration (Optional): Extend Laravel’s Artisan to delegate to Silly:

    use Illuminate\Console\Scheduling\Schedule;
    use Silly\Application;
    
    protected function schedule(Schedule $schedule)
    {
        $silly = new Application();
        $silly->command('schedule:run', function () {
            // Silly command logic
        });
        $silly->run();
    }
    
  4. Dependency Injection: Leverage Laravel’s container for services:

    $silly->command('db:backup', function (\Illuminate\Filesystem\Filesystem $filesystem) {
        $filesystem->ensureDirectoryExists(storage_path('backups'));
    });
    

Common Patterns

  • Closure-Based Commands: Use for simple, one-off tasks:

    $silly->command('cache:clear', function () {
        Artisan::call('cache:clear');
    });
    
  • Class-Based Commands: For reusable logic with DI:

    $silly->command('migrate', [App\Console\MigrateCommand::class, 'handle']);
    
  • SymfonyStyle Integration: Enhance output with styled prompts:

    $silly->command('deploy', function (\Symfony\Component\Console\Style\SymfonyStyle $io) {
        $io->title('Deploying...');
        $io->section('Steps');
        $io->list(['Step 1', 'Step 2']);
    });
    
  • Subcommands: Organize commands hierarchically:

    $silly->command('user:list', function () { /* ... */ });
    $silly->command('user:create', function () { /* ... */ });
    

Gotchas and Tips

Pitfalls

  1. Parameter Order Sensitivity: Silly matches parameters by name, not position. Mixing command arguments with DI parameters may cause unexpected behavior if names collide. Fix: Use explicit type-hints for DI parameters:

    $silly->command('user:create [name]', function (UserRepository $users, $name) {
        $users->create($name);
    });
    
  2. Container Binding Conflicts: If using Laravel’s container, ensure Silly’s container isn’t overridden: Fix: Register Silly’s container after Laravel’s bindings:

    $silly->useContainer(app(), true, true); // Enable type-hint and name injection
    
  3. Hyphen to CamelCase Conversion: Options like --dry-run become $dryRun in the closure. Forgetting this causes Undefined variable errors. Fix: Use snake_case in closures if preferred:

    $silly->command('run [--dry-run]', function ($dry_run) { /* ... */ });
    
  4. Default Values Override: Explicit defaults in ->defaults() override closure defaults:

    $silly->command('greet [name]', function ($name = 'Guest') { /* ... */ })
           ->defaults(['name' => 'User']);
    

    Result: $name will always be 'User'.

  5. PHP-DI Autowiring: If using silly-php-di, ensure your classes are autoloaded and follow PSR-4 conventions.

Debugging Tips

  • Inspect Input/Output: Use var_dump($input->getArguments()) or var_dump($input->getOptions()) to debug command parsing.
  • Enable Verbose Mode: Pass --verbose to Silly commands to see execution flow:
    php artisan.php --verbose user:create John
    
  • Check Container Resolutions: For DI issues, verify the container can resolve the service:
    if (!app()->has(UserRepository::class)) {
        throw new \RuntimeException('UserRepository not bound!');
    }
    

Extension Points

  1. Custom Command Helpers: Extend Silly’s Application to add reusable methods:

    class CustomApplication extends Application
    {
        public function commandWithLogging($name, $callback)
        {
            return $this->command($name, function ($input, $output, $callback) {
                $output->writeln('<info>Executing...</info>');
                $callback($input, $output);
            });
        }
    }
    
  2. Middleware for Commands: Use closures to wrap commands (e.g., for auth):

    $silly->command('admin:task', function ($input, $output) {
        if (!auth()->check()) {
            $output->writeln('Unauthorized!');
            return;
        }
        // Proceed with command
    });
    
  3. Event Listeners: Attach listeners to command execution:

    $silly->on('command.test', function ($event) {
        Log::info('Command "test" started', ['input' => $event->getInput()]);
    });
    
  4. Laravel Mix Integration: Use Silly for build scripts in webpack.mix.js:

    mix.silly('build', function () {
        mix.js('resources/js/app.js', 'public/js');
    });
    

Performance Quirks

  • Avoid Heavy DI in Closures: Closures with complex DI chains may slow down command registration. Prefer class-based commands for heavy logic.
  • Cache Command Definitions: If using Silly in a long-running process (e.g., Laravel Tinker), cache the Application instance:
    $silly = app('silly'); // Reuse instance
    

Laravel-Specific Tips

  • Artisan Command Aliases: Register Silly commands as Artisan commands for consistency:

    Artisan::add(new class extends Command {
        protected $signature = 'silly:greet {name?}';
        public function handle() {
            $silly = app('silly');
            $silly->run(['greet', $this->argument('name')]);
        }
    });
    
  • Service Container Binding: Bind Silly’s container to Laravel’s container for global access:

    $this->app->instance('silly', $silly);
    
  • Testing: Use Laravel’s Artisan::call() to test Silly commands:

    $this->artisan('silly:greet John')
         ->expectsOutput('Hello, John!')
         ->assertExitCode(0);
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor