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.
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:
Install the package (as a dev dependency if tooling-only):
composer require --dev sebastian/cli-parser
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";
Run the script:
php custom-script.php --verbose --output=report.json --limit=50
Key Laravel Caveat:
Symfony\Component\Console\Input\ArgvInput or Laravel’s Artisan::input().Use this for internal tools, migration helpers, or CI/CD scripts where Symfony Console is overkill.
// 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.");
}
opis/validation for structured input validation:
use Opis\Closure\validate;
$validated = validate($options, [
'env' => 'required|in:production,staging,local',
'dry-run' => 'boolean',
]);
\Log::debug('Parsed options:', $options);
Replace ad-hoc getopt() or manual $argv parsing with this package for consistency.
$shortopts = "vho:";
$longopts = ["verbose", "help", "output:"];
$options = getopt($shortopts, $longopts);
sebastian/cli-parser):$parser = new Parser();
$options = $parser->parse($_SERVER['argv'], [
'verbose' => null, // --verbose
'help' => null, // --help
'output:' => null, // --output=file.txt
]);
If you must use this in an Artisan command (not recommended), isolate parsing in a service class to avoid conflicts with Symfony Console.
// 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',
]);
}
}
// 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']}");
}
}
No Symfony Console Integration
Limited Option Types
--tag=one --tag=two).app:user:create).$tags = [];
if (isset($options['tag'])) {
$tags = explode(',', $options['tag']);
}
PHP Version Constraints
^4.2 in composer.json:
"require-dev": {
"sebastian/cli-parser": "^4.2"
}
No Auto-Generated Help
--help text.symfony/console for help.Argument Order Sensitivity
$argv. For example:
# Works: --output=file.txt input.txt
# Fails: input.txt --output=file.txt
$argv or use a wrapper to separate options/arguments.Inspect Raw $argv
echo "Raw argv: " . implode(' | ', $_SERVER['argv']) . "\n";
Enable Strict Mode
$parser = new Parser();
$parser->setStrictMode(true); // Throws exceptions for unknown options
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);
}
Custom Option Definitions
$definition = [
'port:' => function ($value) {
if (!is_numeric($value)) {
throw new \InvalidArgumentException("Port must be numeric.");
}
return (int) $value;
},
];
Post-Processing
$options['limit'] = (int) $options['limit'];
$options['active'] = (bool) $options['active'];
Integration with Laravel’s Input
$artisanInput = $this->input();
$customOptions = $parser->parse($_SERVER['argv'], $definition);
$merged = array_merge($artisanInput->all(), $customOptions);
Artisan Command Conflicts
--custom-flag) in both:
$signature.sebastian/cli-parser definition.Service Container Binding
Testing
$_SERVER['argv'] inHow can I help you explore Laravel packages today?