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

Cli Parser Laravel Package

sebastian/cli-parser

Parse PHP CLI arguments from $_SERVER['argv'] with a small, focused library extracted from PHPUnit. Ideal for building command-line tools and test runners, providing straightforward handling of options and parameters with minimal dependencies.

View on GitHub
Deep Wiki
Context7

Getting Started

For Laravel developers, this package is not a primary tool but can be useful for standalone CLI scripts or non-Artisan utilities. If you’re building a custom CLI tool outside Laravel’s Artisan ecosystem, follow these minimal steps:

  1. Install the package (as a dev dependency if tooling-only):

    composer require --dev sebastian/cli-parser
    
  2. Basic usage in a script (e.g., custom-script.php):

    <?php
    require __DIR__.'/vendor/autoload.php';
    
    use SebastianBergmann\CliParser\Parser;
    
    $parser = new Parser();
    $options = $parser->parse($_SERVER['argv'], [
        'verbose'   => null,       // Boolean flag (e.g., `--verbose`)
        'output:'   => 'file.txt', // Option with value (e.g., `--output=file.txt`)
        'limit:'    => 10,         // Option with default value
    ]);
    
    // Access parsed values
    if ($options['verbose']) {
        echo "Verbose mode enabled\n";
    }
    echo "Output file: {$options['output']}\n";
    
  3. Run the script:

    php custom-script.php --verbose --output=report.json --limit=50
    

Key Laravel Caveat:

  • Avoid using this in Artisan commands. Laravel’s CLI layer (Symfony Console) already handles parsing. This package is for non-Artisan scripts or legacy codebases.
  • If you need CLI parsing inside Laravel, use Symfony\Component\Console\Input\ArgvInput or Laravel’s Artisan::input().

Implementation Patterns

1. Standalone Scripts (Recommended Use Case)

Use this for internal tools, migration helpers, or CI/CD scripts where Symfony Console is overkill.

Workflow:

// parse.php
$parser = new Parser();
$options = $parser->parse($_SERVER['argv'], [
    'env:'      => 'production', // Required option
    'dry-run'   => false,         // Boolean flag
    'files[]'   => [],            // Multi-value (not natively supported; see "Gotchas")
]);

// Validate and act
if (!$options['env']) {
    throw new \RuntimeException("Environment not specified.");
}

Integration Tips:

  • Combine with opis/validation for structured input validation:
    use Opis\Closure\validate;
    
    $validated = validate($options, [
        'env' => 'required|in:production,staging,local',
        'dry-run' => 'boolean',
    ]);
    
  • Log parsed options for debugging:
    \Log::debug('Parsed options:', $options);
    

2. Legacy Code Migration

Replace ad-hoc getopt() or manual $argv parsing with this package for consistency.

Before (Manual Parsing):

$shortopts = "vho:";
$longopts = ["verbose", "help", "output:"];
$options = getopt($shortopts, $longopts);

After (Using sebastian/cli-parser):

$parser = new Parser();
$options = $parser->parse($_SERVER['argv'], [
    'verbose' => null,   // --verbose
    'help'    => null,   // --help
    'output:' => null,   // --output=file.txt
]);

3. Artisan Command Helpers (Advanced)

If you must use this in an Artisan command (not recommended), isolate parsing in a service class to avoid conflicts with Symfony Console.

Example:

// app/Services/CliParserService.php
namespace App\Services;

use SebastianBergmann\CliParser\Parser;

class CliParserService
{
    public function parseCustomArgs(array $argv): array
    {
        $parser = new Parser();
        return $parser->parse($argv, [
            'custom-flag' => null,
            'custom-value:' => 'default',
        ]);
    }
}

Usage in Artisan Command:

// app/Console/Commands/CustomCommand.php
namespace App\Console\Commands;

use App\Services\CliParserService;
use Illuminate\Console\Command;

class CustomCommand extends Command
{
    protected $signature = 'custom:parse {--custom-flag} {--custom-value=}';
    protected $description = 'Example of mixing parsers (not recommended)';

    public function handle(CliParserService $parser)
    {
        // Parse Artisan args (Symfony Console)
        $artisanArgs = $this->option('custom-flag');

        // Parse additional args (sebastian/cli-parser)
        $customArgs = $parser->parse($_SERVER['argv'], [
            'custom-value:' => null,
        ]);

        $this->info("Artisan flag: $artisanArgs");
        $this->info("Custom value: {$customArgs['custom-value']}");
    }
}

Gotchas and Tips

Pitfalls

  1. No Symfony Console Integration

    • Problem: This package does not work with Artisan’s input/output. Mixing it with Symfony Console can cause duplicate parsing or inconsistent behavior.
    • Fix: Use this only in standalone scripts, not Artisan commands.
  2. Limited Option Types

    • Problem: No native support for:
      • Multi-value options (e.g., --tag=one --tag=two).
      • Subcommands (e.g., app:user:create).
      • Arrays or complex defaults.
    • Workaround: Manually post-process options:
      $tags = [];
      if (isset($options['tag'])) {
          $tags = explode(',', $options['tag']);
      }
      
  3. PHP Version Constraints

    • Problem: v5.0+ drops PHP 8.2 support. Laravel typically uses PHP 8.1+.
    • Fix: Pin to ^4.2 in composer.json:
      "require-dev": {
          "sebastian/cli-parser": "^4.2"
      }
      
  4. No Auto-Generated Help

    • Problem: Unlike Symfony Console, this package does not generate --help text.
    • Fix: Manually document usage or use a library like symfony/console for help.
  5. Argument Order Sensitivity

    • Problem: Options must appear before arguments in $argv. For example:
      # Works: --output=file.txt input.txt
      # Fails: input.txt --output=file.txt
      
    • Fix: Reorder $argv or use a wrapper to separate options/arguments.

Debugging Tips

  1. Inspect Raw $argv

    echo "Raw argv: " . implode(' | ', $_SERVER['argv']) . "\n";
    
    • Helps diagnose why parsing fails (e.g., unquoted spaces, missing flags).
  2. Enable Strict Mode

    $parser = new Parser();
    $parser->setStrictMode(true); // Throws exceptions for unknown options
    
  3. Handle Unknown Options Gracefully

    try {
        $options = $parser->parse($_SERVER['argv'], $definition);
    } catch (\SebastianBergmann\CliParser\Exception\UnknownOption $e) {
        $this->error("Unknown option: " . $e->getOption());
        exit(1);
    }
    

Extension Points

  1. Custom Option Definitions

    • Use callbacks for dynamic validation:
      $definition = [
          'port:' => function ($value) {
              if (!is_numeric($value)) {
                  throw new \InvalidArgumentException("Port must be numeric.");
              }
              return (int) $value;
          },
      ];
      
  2. Post-Processing

    • Normalize parsed values:
      $options['limit'] = (int) $options['limit'];
      $options['active'] = (bool) $options['active'];
      
  3. Integration with Laravel’s Input

    • If you must use this in a Laravel context, merge parsed options with Symfony’s input:
      $artisanInput = $this->input();
      $customOptions = $parser->parse($_SERVER['argv'], $definition);
      $merged = array_merge($artisanInput->all(), $customOptions);
      

Laravel-Specific Quirks

  1. Artisan Command Conflicts

    • If you define a custom option (e.g., --custom-flag) in both:
      • Artisan’s $signature.
      • sebastian/cli-parser definition.
    • Result: The last parser wins. Avoid overlap.
  2. Service Container Binding

    • You cannot bind this parser to Laravel’s container because it’s not a Symfony service. Use a facade or service class instead.
  3. Testing

    • Mock $_SERVER['argv'] in
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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle