{"id":13518334,"url":"https://github.com/shipmonk-rnd/composer-dependency-analyser","last_synced_at":"2025-05-14T08:09:29.350Z","repository":{"id":214452157,"uuid":"736211524","full_name":"shipmonk-rnd/composer-dependency-analyser","owner":"shipmonk-rnd","description":"🚀 Fast detection of composer dependency issues (unused dependencies, shadow dependencies, misplaced dependencies)","archived":false,"fork":false,"pushed_at":"2025-02-10T13:31:59.000Z","size":395,"stargazers_count":505,"open_issues_count":11,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-05-12T05:05:25.570Z","etag":null,"topics":["analyzer","checker","composer","dead-code","dependencies","require","soft-dependencies","unused-dependencies"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shipmonk-rnd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-12-27T09:32:43.000Z","updated_at":"2025-05-02T14:37:45.000Z","dependencies_parsed_at":"2024-03-14T11:32:33.996Z","dependency_job_id":"feea5646-4329-4d51-8911-a07513138180","html_url":"https://github.com/shipmonk-rnd/composer-dependency-analyser","commit_stats":null,"previous_names":["shipmonk-rnd/composer-dependency-analyser"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shipmonk-rnd%2Fcomposer-dependency-analyser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shipmonk-rnd%2Fcomposer-dependency-analyser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shipmonk-rnd%2Fcomposer-dependency-analyser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shipmonk-rnd%2Fcomposer-dependency-analyser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shipmonk-rnd","download_url":"https://codeload.github.com/shipmonk-rnd/composer-dependency-analyser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101558,"owners_count":22014908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analyzer","checker","composer","dead-code","dependencies","require","soft-dependencies","unused-dependencies"],"created_at":"2024-08-01T05:01:43.693Z","updated_at":"2025-05-14T08:09:24.341Z","avatar_url":"https://github.com/shipmonk-rnd.png","language":"PHP","funding_links":[],"categories":["PHP","Programming Languages","Development Tools","Plugins"],"sub_categories":["PHP Dev Tools","Support"],"readme":"# Composer dependency analyser\n\n- 💪 **Powerful:** Detects unused, shadow and misplaced composer dependencies\n- ⚡ **Performant:** Scans 15 000 files in 2s!\n- ⚙️ **Configurable:** Fine-grained ignores via PHP config\n- 🕸️ **Lightweight:** No composer dependencies\n- 🍰 **Easy-to-use:** No config needed for first try\n- ✨ **Compatible:** PHP 7.2 - 8.4\n\n## Comparison:\n\n| Project                                   | Dead\u003cbr/\u003edependency | Shadow\u003cbr/\u003edependency  | Misplaced\u003cbr/\u003ein `require` | Misplaced\u003cbr/\u003e in `require-dev` | Time*      |\n|-------------------------------------------|---------------------|------------------------|--------------------------|-------------------------------|------------|\n| maglnet/\u003cbr/\u003e**composer-require-checker**          | ❌                   | ✅                     | ❌                         |  ❌                             | 124 secs   |\n| icanhazstring/\u003cbr/\u003e**composer-unused**             | ✅                   | ❌                     | ❌                         |  ❌                             | 72 secs    |\n| shipmonk/\u003cbr/\u003e**composer-dependency-analyser** | ✅                   | ✅                     | ✅                         |  ✅                             | **2 secs** |\n\n\u003csup\u003e\u003csub\u003e\\*Time measured on codebase with ~15 000 files\u003c/sub\u003e\u003c/sup\u003e\n\n## Installation:\n\n```sh\ncomposer require --dev shipmonk/composer-dependency-analyser\n```\n\n*Note that this package itself has **zero composer dependencies.***\n\n## Usage:\n\n```sh\nvendor/bin/composer-dependency-analyser\n```\n\nExample output:\n```txt\n\nFound shadow dependencies!\n(those are used, but not listed as dependency in composer.json)\n\n  • nette/utils\n    e.g. Nette\\Utils\\Strings in app/Controller/ProductController.php:24 (+ 6 more)\n\nFound unused dependencies!\n(those are listed in composer.json, but no usage was found in scanned paths)\n\n  • nette/utils\n\n(scanned 13970 files in 2.297 s)\n```\n\n## Detected issues:\nThis tool reads your `composer.json` and scans all paths listed in `autoload` \u0026 `autoload-dev` sections while analysing you dependencies (both **packages and PHP extensions**).\n\n### Shadowed dependencies\n  - Those are dependencies of your dependencies, which are not listed in `composer.json`\n  - Your code can break when your direct dependency gets updated to newer version which does not require that shadowed dependency anymore\n  - You should list all those packages within your dependencies\n\n### Unused dependencies\n  - Any non-dev dependency is expected to have at least single usage within the scanned paths\n  - To avoid false positives here, you might need to adjust scanned paths or ignore some packages by `--config`\n\n### Dev dependencies in production code\n  - For libraries, this is risky as your users might not have those installed\n  - For applications, it can break once you run it with `composer install --no-dev`\n  - You should move those from `require-dev` to `require`\n\n### Prod dependencies used only in dev paths\n  - For libraries, this miscategorization can lead to uselessly required dependencies for your users\n  - You should move those from `require` to `require-dev`\n\n### Unknown classes\n  - Any class that cannot be autoloaded gets reported as we cannot say if that one is shadowed or not\n\n### Unknown functions\n  - Any function that is used, but not defined during runtime gets reported as we cannot say if that one is shadowed or not\n\n## Cli options:\n- `--composer-json path/to/composer.json` for custom path to composer.json\n- `--dump-usages symfony/console` to show usages of certain package(s), `*` placeholder is supported\n- `--config path/to/config.php` for custom path to config file\n- `--version` display version\n- `--help` display usage \u0026 cli options\n- `--verbose` to see more example classes \u0026 usages\n- `--show-all-usages` to see all usages\n- `--format` to use different output format, available are: `console` (default), `junit`\n- `--disable-ext-analysis` to disable php extensions analysis (e.g. `ext-xml`)\n- `--ignore-unknown-classes` to globally ignore unknown classes\n- `--ignore-unknown-functions` to globally ignore unknown functions\n- `--ignore-shadow-deps` to globally ignore shadow dependencies\n- `--ignore-unused-deps` to globally ignore unused dependencies\n- `--ignore-dev-in-prod-deps` to globally ignore dev dependencies in prod code\n- `--ignore-prod-only-in-dev-deps` to globally ignore prod dependencies used only in dev paths\n\n\n## Configuration:\nWhen a file named `composer-dependency-analyser.php` is located in cwd, it gets loaded automatically.\nThe file must return `ShipMonk\\ComposerDependencyAnalyser\\Config\\Configuration` object.\nYou can use custom path and filename via `--config` cli option.\nHere is example of what you can do:\n\n```php\n\u003c?php\n\nuse ShipMonk\\ComposerDependencyAnalyser\\Config\\Configuration;\nuse ShipMonk\\ComposerDependencyAnalyser\\Config\\ErrorType;\n\n$config = new Configuration();\n\nreturn $config\n     //// Adjusting scanned paths\n    -\u003eaddPathToScan(__DIR__ . '/build', isDev: false)\n    -\u003eaddPathToExclude(__DIR__ . '/samples')\n    -\u003edisableComposerAutoloadPathScan() // disable automatic scan of autoload \u0026 autoload-dev paths from composer.json\n    -\u003esetFileExtensions(['php']) // applies only to directory scanning, not directly listed files\n\n    //// Ignoring errors\n    -\u003eignoreErrors([ErrorType::DEV_DEPENDENCY_IN_PROD])\n    -\u003eignoreErrorsOnPath(__DIR__ . '/cache/DIC.php', [ErrorType::SHADOW_DEPENDENCY])\n    -\u003eignoreErrorsOnPackage('symfony/polyfill-php73', [ErrorType::UNUSED_DEPENDENCY])\n    -\u003eignoreErrorsOnPackageAndPath('symfony/console', __DIR__ . '/src/OptionalCommand.php', [ErrorType::SHADOW_DEPENDENCY])\n\n    //// Ignoring unknown symbols\n    -\u003eignoreUnknownClasses(['Memcached'])\n    -\u003eignoreUnknownClassesRegex('~^DDTrace~')\n    -\u003eignoreUnknownFunctions(['opcache_invalidate'])\n    -\u003eignoreUnknownFunctionsRegex('~^opcache_~')\n\n    //// Adjust analysis\n    -\u003eenableAnalysisOfUnusedDevDependencies() // dev packages are often used only in CI, so this is not enabled by default\n    -\u003edisableReportingUnmatchedIgnores() // do not report ignores that never matched any error\n    -\u003edisableExtensionsAnalysis() // do not analyse ext-* dependencies\n\n    //// Use symbols from yaml/xml/neon files\n    // - designed for DIC config files (see below)\n    // - beware that those are not validated and do not even trigger unknown class error\n    -\u003eaddForceUsedSymbols($classesExtractedFromNeonJsonYamlXmlEtc)\n```\n\nAll paths are expected to exist. If you need some glob functionality, you can do it in your config file and pass the expanded list to e.g. `ignoreErrorsOnPaths`.\n\n### Detecting classes from non-php files:\n\nSome classes might be used only in your DIC config files. Here is a simple way to extract those:\n\n```php\n$classNameRegex = '[a-zA-Z_\\x80-\\xff][a-zA-Z0-9_\\x80-\\xff]*'; // https://www.php.net/manual/en/language.oop5.basic.php\n$dicFileContents = file_get_contents(__DIR__ . '/config/services.yaml');\n\npreg_match_all(\n    \"~$classNameRegex(?:\\\\\\\\$classNameRegex)+~\", // at least one backslash\n    $dicFileContents,\n    $matches\n); // or parse the yaml properly\n\n$config-\u003eaddForceUsedSymbols($matches[1]); // possibly filter by class_exists || interface_exists\n```\n\nSimilar approach should help you to avoid false positives in unused dependencies.\nAnother approach for DIC-only usages is to scan the generated php file, but that gave us worse results.\n\n### Scanning codebase located elsewhere:\n- This can be done by pointing `--composer-json` to `composer.json` of the other codebase\n\n### Disable colored output:\n- Set `NO_COLOR` environment variable to disable colored output:\n```\nNO_COLOR=1 vendor/bin/composer-dependency-analyser\n```\n\n## Recommendations:\n- For precise `ext-*` analysis, your enabled extensions of your php runtime should be superset of those used in the scanned project\n\n## Contributing:\n- Check your code by `composer check`\n- Autofix coding-style by `composer fix:cs`\n- All functionality must be tested\n\n## Supported PHP versions\n- Runtime requires PHP 7.2 - 8.4\n- Scanned codebase should use PHP \u003e= 5.3\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshipmonk-rnd%2Fcomposer-dependency-analyser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshipmonk-rnd%2Fcomposer-dependency-analyser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshipmonk-rnd%2Fcomposer-dependency-analyser/lists"}