Weave 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

Composer Parser Laravel Package

mcstreetguy/composer-parser

A PHP library for parsing composer.json and composer.lock files into structured, object-oriented data. It exposes package metadata, dependencies, version constraints, and lockfile contents, making Composer projects easy to inspect programmatically.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a small, single-purpose OOP wrapper around composer.json: it reads the file and exposes the schema (require, require-dev, authors, autoload, scripts, etc.) as typed objects instead of a raw array. It was last released in September 2019, has zero dependents, and no commits since — treat it as a "read the source before you composer require" dependency, not a drop-in framework component.

Install

composer require mcstreetguy/composer-parser

Before committing to it, verify two things:

  1. PHP compatibility. Check composer.json's require constraint and the CI matrix. A 2019 package predates PHP 8 typed properties and PHP 8.1 deprecations; if you're on 8.2+ you may need --ignore-platform-reqs or a fork.
  2. Autoload namespace. Confirm the PSR-4 root (it will be under MCStreetguy\ComposerParser\...) with composer dump-autoload -o and a quick php -r "var_dump(class_exists('MCStreetguy\\ComposerParser\\...'));".

Where to look first

  • README.md — the only usage documentation; read it completely, it's short.
  • src/ — the entry point is a parser/factory class in the root namespace; the domain objects (ComposerFile, author, autoload, requirement models) live in sub-namespaces. Skim these to see what fields actually round-trip.
  • tests/ — the best source of truth for supported composer.json shapes. If a fixture isn't there, assume it isn't handled.

First use case: a composer:inspect artisan command

The realistic day-to-day value in a Laravel app is introspection of your own project manifest — not of vendor/. A first command that dumps your app's declared requirements is the fastest way to validate the API:

// app/Console/Commands/InspectComposer.php
public function handle()
{
    $path = base_path('composer.json');

    // Verify the exact factory class name against the README / src.
    $composer = \MCStreetguy\ComposerParser\...::parse($path);

    $this->table(['Package', 'Constraint'], collect($composer->getRequire())
        ->map(fn ($constraint, $package) => [$package, $constraint])
        ->values()->all());
}

If the above compiles and returns your require block, you've confirmed the package works on your PHP version and you can build on it. If it throws on autoload or type errors, stop here and use composer/composer's ArrayLoader instead (see Gotchas).

Implementation Patterns

Wrap it, don't sprinkle it. Bind a single accessor in a service provider so parsing happens once and the rest of the app depends on your interface, not the package's concrete classes. That makes swapping to composer/composer later a one-file change.

// app/Providers/ComposerParserServiceProvider.php
$this->app->singleton(ProjectManifest::class, fn () => new ProjectManifest(
    base_path('composer.json')
));

Cache the parse, not the file. composer.json changes only on deploy, so parse once and cache the serialized object or a plain array:

$manifest = Cache::rememberForever('composer.manifest', function () {
    return ProjectManifest::from(base_path('composer.json'))->toArray();
});

Invalidate in your deploy script (a php artisan cache:forget composer.manifest step) rather than at runtime.

Map into your own DTOs. The package's objects are tied to a 2019 design. Ingest them once at the boundary and convert to arrays or your own value objects so the rest of the codebase isn't coupled to a package with no maintenance.

Use it for reporting, not for resolution. Good fits:

  • A "dependencies" admin page listing declared packages and constraints.
  • A license audit: collect license strings across composer.json and a hand-rolled scan of vendor/*/composer.json.
  • A deploy-time sanity check that require and require-dev meet your house rules (e.g. no * constraints, pinned major versions).

Bad fits: resolving constraints, deciding what's installed, or anything involving composer.lock semantics. For those, use composer/semver and Composer's own InstalledVersions / vendor/composer/installed.json.

Scanning multiple manifests. If your goal is "what do my dependencies declare?", iterate glob(base_path('vendor/*/*/composer.json')) and parse each — but skip anything under vendor/bin and guard every file with is_readable(). Wrap each parse in a try/catch; one malformed dependency manifest should not break your report.

$rows = collect(glob(base_path('vendor/*/*/composer.json')))
    ->filter(fn ($f) => is_readable($f))
    ->map(function ($f) {
        try { return ProjectManifest::from($f)->toArray(); }
        catch (\Throwable $e) { report($e); return null; }
    })
    ->filter()
    ->values();

Gotchas and Tips

It is effectively unmaintained. Seven stars, zero dependents, no release since 2019. That's not disqualifying for a ~500-line read-only parser, but it means: pin the exact version in composer.json (not ^), do not use it inside a package you intend to publish, and expect to fork it if PHP 8.x compatibility bites.

Don't use it to answer "is X installed?" The parser reads a manifest; it doesn't read the lock file or the vendor tree. Use composer show, Composer\InstalledVersions::isInstalled(), or vendor/composer/installed.json for that. Getting this wrong is the number one footgun — a require entry is a constraint, not an installed fact.

Constraint strings are strings. getRequire() returns the raw constraint (^10.0|^11.0). Don't hand-roll version comparison; feed it to composer/semver's VersionParser and Semver::satisfies().

The schema drifts faster than the package. composer.json gained config.allow-plugins, require-dev conventions, funding, archive, and other keys over the years. A 2019 parser may throw or silently drop unknown keys. Inspect the model classes to see whether unknown fields are preserved; if not, fall back to json_decode for anything exotic.

Path handling. Never pass user-supplied input to the parser. If you must take a path, resolve with realpath() and assert it's inside base_path() to avoid path-traversal reads. composer.json may also be a symlink in some CI setups — test with both.

Malformed JSON throws; plan for it. Composer allows no trailing commas and no comments. Wrap every parse in a try/catch, log the file path and the previous exception, and return an empty/default manifest rather than fatally erroring a page render.

Extension points exist but are lightly documented. The parser is OOP, so there are likely interfaces for the manifest and field models you can implement if the built-in behavior is wrong. Check src/ for interface declarations before you fork — implementing one interface is cheaper than maintaining a fork.

The pragmatic alternative. If you hit friction, composer require composer/composer gives you Composer\Factory plus Composer\Package\Loader\ArrayLoader and Composer\Json\JsonFile, which is the canonical, actively maintained path to the same data:

$json = new \Composer\Json\JsonFile(base_path('composer.json'));
$data = $json->read(); // throws on invalid JSON, strict-schema aware

For a Laravel app, that's the safer default. Reach for mcstreetguy/composer-parser only if you specifically want its small object model and are willing to pin and possibly patch it.

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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib