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 Require Checker Laravel Package

maglnet/composer-require-checker

ComposerRequireChecker is a CLI tool that analyzes your composer.json and source code to find unknown symbols and soft/transitive dependencies. It flags code relying on packages or PHP extensions you haven't explicitly required, helping prevent unexpected breakage from dependency updates.

View on GitHub
Deep Wiki
Context7

Getting Started

ComposerRequireChecker is a CLI tool, not a library — you don't require it into a project. In a Laravel codebase the fastest path is the PHAR:

# Download once, keep it out of the repo (or gitignore it)
curl -L -o composer-require-checker.phar \
  https://github.com/maglnet/ComposerRequireChecker/releases/latest/download/composer-require-checker.phar
chmod +x composer-require-checker.phar

# Baseline run against your app
composer install
php composer-require-checker.phar check composer.json

Alternatives: phive install composer-require-checker if you use Phive for tooling, or composer global require maglnet/composer-require-checker to get a composer-require-checker binary on your PATH. Do not add it to require-dev — it drags in symfony/console, nikic/php-parser, etc., and pollutes the very dependency graph it's supposed to audit.

Where to look first:

  1. Run the bare command against a freshly composer installed Laravel app. You'll likely get a mix of core-symbol whitelist complaints and genuine soft dependencies — this is your baseline.
  2. Copy the tool's shipped data/config.dist.json (linked from the README) into your project as composer-require-checker.json and edit it. This is the default config filename the tool picks up automatically.
  3. Fix the easy wins first: any guzzlehttp/guzzle, nesbot/carbon, monolog/monolog, symfony/*, league/flysystem, ramsey/uuid, etc. that you use but didn't declare — either add to require/require-dev or, if transitive-by-design, whitelist the specific symbol.

First realistic use case: a Laravel app using Http:: (Guzzle under the hood), Carbon, and Str/Arr helpers. The tool flags every Guzzle class you touched directly, plus any PHP extension functions (e.g. intl, sodium, gd, bcmath, redis) you rely on that aren't in composer.json's require ext-* section.

Implementation Patterns

CI gate (GitHub Actions / GitLab CI)

Keep the PHAR download on every run and cache it keyed by a pinned version, then feed the config file:

# .github/workflows/require-checker.yml
- name: Install ComposerRequireChecker
  run: |
    curl -fsSL -o composer-require-checker.phar \
      https://github.com/maglnet/ComposerRequireChecker/releases/download/4.9.0/composer-require-checker.phar
- name: Check hard dependencies
  run: XDEBUG_MODE=off php composer-require-checker.phar check --config-file=composer-require-checker.json composer.json

Pin a release tag rather than latest — the default core-symbol whitelist shifts between minors (see 4.6.0 adding hash, 4.7.0 touching /etc/shadow detection, 4.8.0 dropping PHP 8.1) and a floating tag can silently fail your build.

Layering the config

The tool reads exactly one config file. That means your project config must be a superset of the dist whitelist. The maintainable pattern:

  1. Start from data/config.dist.json at the version you pin.
  2. Regenerate a copy in a small script (cp vendor/.../config.dist.json or a curl of the tagged file) whenever you bump the tool.
  3. Merge your project-specific additions (scan-files, extra symbol-whitelist entries) into that copy.
  4. Commit the result as composer-require-checker.json.

This avoids the "why is true undefined?" trap that happens when someone hand-writes a minimal config.

Scanning non-autoload files

Laravel has plenty of PHP outside PSR-4 autoloading — bin/artisan style scripts, custom artisan-adjacent entrypoints, deployment scripts. Use scan-files with globs:

{
  "scan-files": ["bin/console", "bin/*.php", "database/seeders/*.php", "routes/*.php"]
}

Where practical, prefer adding the path to composer.json's autoload/autoload-dev (e.g. classmap or files) so the tool's default autoload discovery picks it up and you don't have to maintain a list of globs. Reserve scan-files for files that genuinely shouldn't be autoloaded.

Whitelisting as a review tripwire

Treat additions to symbol-whitelist like a code review event, not a rubber stamp. A good convention: annotate each entry with a // symbol — reason — owner comment (JSON doesn't support comments, so keep a parallel docs/require-checker-whitelist.md if your team values the paper trail). Distinguish two kinds:

  • Core/internal symbols — true, false, null, Traversable, DateTimeInterface, etc. These belong in the inherited dist block; never add anything here by hand unless the tool version didn't ship it.
  • Intentional soft deps — e.g. Psr\Log\LoggerInterface when you only require psr/log indirectly, or a class from a package you deliberately don't want to take a hard dep on. Each one should be a conscious decision.

Extension functions

PHP extension functions surface as unknown symbols when ext-* isn't declared. The tool has a built-in map of core extension → symbols. Two approaches:

  • Preferred: add "ext-intl": "*" (or the real constraint) to composer.json's require block. This is a real correctness fix and makes Composer enforce it.
  • Fallback: whitelist the specific symbols. Only appropriate when the function is genuinely optional behind function_exists().

Local pre-commit hook

Hook it into a composer script so it runs alongside Pint/Stan:

{
  "scripts": {
    "check": [
      "@php vendor/bin/pint --test",
      "@php vendor/bin/phpstan analyse",
      "@php composer-require-checker.phar check --config-file=composer-require-checker.json composer.json"
    ]
  }
}

Guard it behind function_exists('Composer\\Config::disableProcessTimeout') style checks or simply document that contributors need the PHAR installed; otherwise every composer check for a new contributor becomes a scavenger hunt.

Gotchas and Tips

Xdebug breaks it (badly)

The README calls this out for a reason. Xdebug's max-nesting-level and slowdown cause false "exceeded max nesting" errors or timeouts on Laravel-sized codebases. Always run with:

XDEBUG_MODE=off php composer-require-checker.phar check composer.json

Bake this into every CI script and composer script entry. On a large app it's the difference between ~5s and a timeout.

Custom installer plugins break path discovery

The tool reads Composer's vendor-dir from composer.json and assumes standard layout — it does not boot Composer. Anything installed by a composer-plugin to a non-vendor/ path will confuse it. The documented workaround:

composer install --no-plugins
php composer-require-checker.phar check composer.json
composer install

If you rely on installer plugins in your app, make this a dedicated just check-deps / make check-deps recipe rather than something people have to remember by hand.

The config file is all-or-nothing

If you create composer-require-checker.json with only "scan-files" and nothing else, the tool won't apply its default whitelist. Every core symbol (true, null, Traversable, every internal function from every bundled extension) becomes an error. Symptom: your CI suddenly reports hundreds of "undefined symbol true" style failures. Fix: copy the whole dist config, edit inside it. This trips up virtually every new user once.

Default config filename

The tool silently picks up composer-require-checker.json from the current working directory if --config-file isn't passed. This is convenient but hides mistakes: a stray file in a subdirectory won't be found, and CI running from a different directory won't see it. Be explicit in CI: --config-file=$(pwd)/composer-require-checker.json.

Non-composer.json require-style declaration

The tool inspects require and require-dev. If you declare a hard dep only in suggest (common in packages but not apps) it won't count. If your app relies on a class that is only suggest-ed, you'll get a false positive and need a whitelist entry.

Extension function map lags PHP

New extensions and newer core functions occasionally aren't yet in the tool's symbol map. Symptom: an internal function flagged as unknown even though it's obviously core. Check the pinned version's data/extensions.json (or equivalent) for coverage, and either bump the tool or whitelist the function with a comment. The 4.6.0 release notes adding hash are a good example of this drift.

PHP version support churn

4.8.0 dropped PHP 8.1 and added Symfony 7 support; 4.7.0 enabled PHP 8.3. Pin the PHAR version and make sure it's runnable on the oldest PHP you support, or run it only on your newest PHP in CI. Running a too-new PHAR on an old PHP produces fatal errors rather than diagnostics.

Attribute handling is relatively new

4.9.0 added attribute support. If you're on an older 4.x and use PHP attributes (common in Laravel 10+/11 with route/attribute-style configuration), you may see symbols used only in attributes slip through undetected — the inverse of a false positive. Upgrade to ≥4.9.0 before trusting the output on attribute-heavy code.

CI debugging

When the check fails, pipe the output to a file and inspect the "soft dependency" list separately from the "core extension" list. Most failures fall into three buckets: (1) forgot ext-* in require, (2) using a transitive package without declaring it, (3) config whitelist not being applied. Addressing them in that order — extension declarations, then hard-deps, then whitelist — resolves the overwhelming majority of red builds in one pass.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin