nadar/php-composer-reader
Small PHP library to read and manipulate composer.json. Load and validate readability/writability, dump full content, and work with typed section readers (e.g., require, autoload PSR-4) to iterate packages/namespaces, inspect constraints, and add sections.
Use Case Alignment:
allow input from array feature (PR #16) enables programmatic composer.json manipulation without file I/O, critical for:
composer.json clones).composer.json snippets (e.g., for testing).config() system extensions (e.g., config('custom.dependencies') sourced from parsed arrays).command output methods (PR #17) bridge gaps with Laravel’s Artisan commands, enabling:
php artisan dependency:audit).composer script replacements (e.g., post-update-cmd logic in PHP).composer.json array from a config file).Composer\EventDispatcher for post-install hooks (e.g., trigger composer.post-autoload-dump events dynamically).Laravel-Specific Opportunities:
config('app.providers') at runtime (e.g., load providers only if specific packages are installed).composer.json data with Laravel’s config() (e.g., config(['package_versions' => $reader->getVersions()])).Alternatives Revisited:
spatie/laravel-package-tools: Still preferred for package development, but this package now offers low-level control for edge cases (e.g., modifying composer.json in-memory before writing to disk).Composer Facade: Lacks the new array-input and CLI utilities; this package fills gaps for programmatic, non-file-based workflows.PHP 8.3/8.4 Support:
2.0.x to avoid potential strict typing issues.Array Input Feature:
file_get_contents() calls, reducing I/O overhead in:
composer.json in middleware or request pipelines.composer.json without touching disk (e.g., unit tests with mock arrays).require/replace structures).Command Output Methods:
Artisan::call('composer:audit', ['--format' => 'json'])).JsonResponse or Artisan output helpers.Dependency Conflicts:
Low-Moderate (Previously Low):
name field). Mitigation: Validate against Composer schema (e.g., Composer\Semver\VersionParser) before processing.array<string, mixed>). Mitigation: Test with PHP 8.4 in CI.composer.json arrays may cause silent failures. Mitigation: Wrap array input in a try-catch with schema validation.Key Questions Updated:
json_schema or a custom validator?^2.1 (PHP 8.3+) or ~2.0 (PHP 7.4+) for broader compatibility?Cache::remember)?composer.json arrays (e.g., from API inputs), how will you prevent injection attacks (e.g., arbitrary code in autoload scripts)?PHP/Laravel: Enhanced Fit with new features:
json_decode(file_get_contents()) in all use cases (runtime, testing, CLI).Artisan and JsonResponse.Use Cases Expanded:
| Feature | Laravel Integration Example |
|---|---|
| Array Input | config(['dynamic_providers' => $reader->parse($arrayConfig)]) |
| Command Output | Artisan::output($reader->getCommandOutput('json')) |
| PHP 8.3+ Support | Laravel 10+ projects without version conflicts. |
Phase 0: Prep Work (New)
php.ini or Laravel’s php-version config if needed.webmozart/assert or json_schema).Phase 1: Replace File Parsing (Updated)
json_decode(file_get_contents(base_path('composer.json')))$reader->parse(file: false, array: $composerJsonArray)$reader = app(Nadar\ComposerReader\ComposerJsonReader::class);
$config = $reader->parse(array: [
'name' => 'app/package',
'require' => ['laravel/framework' => '^10.0'],
]);
Phase 2: CLI/Artisan Integration (New)
use Nadar\ComposerReader\ComposerJsonReader;
class AuditCommand extends Command {
protected function handle() {
$reader = new ComposerJsonReader();
$this->output->write($reader->getCommandOutput('table'));
}
}
AppServiceProvider:
$this->app->singleton(ComposerJsonReader::class, fn() => new ComposerJsonReader());
Phase 3: Dynamic Runtime Logic (Updated)
$reader = app(ComposerJsonReader::class);
$packages = $reader->parse()->getPackages();
if ($packages['monolog/monolog'] ?? false) {
Config::set('app.providers', array_merge(config('app.providers'), [MonologServiceProvider::class]));
}
2.0.x.composer validate in CI to catch drift.array<string, mixed>) are optional.file_get_contents() calls with array input (lowest risk).How can I help you explore Laravel packages today?