cmgmyr/phploc
Measure the size and structure of a PHP project with phploc: lines of code, cyclomatic complexity, dependencies, and class counts, right from the command line.
Architecture fit
cmgmyr/phploc is a standalone Symfony Console CLI application, not a Laravel package and not a library with a consumable API. There is no service provider, no facade, no config file, and no Laravel auto-discovery (extra.laravel) entry. Any integration work therefore lands in the build/tooling layer, not the application layer — which is the right place for a code-metrics tool, but it means a TPM should budget for CI plumbing and report parsing, not for "install and configure."Integration feasibility
composer require --dev cmgmyr/phploc and invoke vendor/bin/phploc from a CI job or a local script. No credentials, no services, no database.composer global install, which a TPM should steer the team away from — global installs are unreproducible across CI runners. Pin it as a dev dependency with a locked version instead.Technical risk (this is the dominant dimension)
phploc. The fork renamed the namespace from SebastianBergmann\PHPLOC to Cmgmyr\PHPLOC (8.0.0). That is a hard breaking change relative to every existing phploc article, snippet, and third-party integration — you cannot follow upstream docs verbatim and you cannot swap binaries without checking namespace-dependent code.^8.1 → ^7.4 || ^8.0 (8.0.1), "expanded dependencies to handle both PHPUnit 9 and 10" (8.0.2), "rm use of version dependency" (8.0.3), then 8.0.8 allowing php-file-iterator ^7.0 and cli-parser ^5.0. This is a maintainer reactively chasing Composer conflicts — and php-file-iterator is also a PHPUnit dependency, which is precisely where a dev-dependency conflict will surface in a Laravel repo that already runs PHPUnit or Pest.phploc analyses source via a PHP tokenizer. Modern PHP and modern Laravel codebases lean heavily on enums, readonly properties, attributes, first-class callables, and promoted constructor properties. A fork whose release notes are entirely dependency bumps and a foreach revert carries no evidence of PHP 8.2/8.3 syntax coverage. Expect possible analyser warnings or mis-parsed complexity in newer files.Key questions to put to engineering before approval
php-file-iterator ^7.0 / cli-parser ^5.0 set actually resolve alongside our current PHPUnit/Pest and PHP version, or does it force a dev-dependency downgrade?--log-*, or is the output text-only? (Determines whether the dashboard story is cheap or expensive.)cmgmyr/phploc, or do we pin upstream sebastianbergmann/phploc and lose nothing but recency? The fork's only user-visible delta is the namespace — a TPM should ask what capability we are actually buying.Stack fit
require-dev only. It must not appear in the production image or the deploy artifact — treat it as a linting-class tool.phpmetrics if a richer HTML view is wanted. phploc is the cheap, fast summary in that set; it is not a substitute for static analysis.Migration path
composer require --dev cmgmyr/phploc:8.0.8, run vendor/bin/phploc app/ and vendor/bin/phploc app/ --exclude vendor --exclude storage. Capture the raw output as the first baseline.sebastianbergmann/phploc vs. this fork. Compare numbers field-by-field. If they match, the fork buys nothing and you should default to upstream for lower risk; if the fork is materially better on current PHP, document why.Compatibility considerations
^7.4 || ^8.0. Confirm actual behaviour on your current PHP 8.2/8.3 runtime — the constraint says "allowed," not "tested."php-file-iterator / cli-parser version floors introduced in 8.0.8 are the single most likely install blocker. Run composer why-not cmgmyr/phploc 8.0.8 before committing to it in a repo with an established PHPUnit lockfile.8.0.8, no caret) and commit the lockfile. In a fork with 0 dependents, "latest" is not a safety property.vendor/, storage/framework/views/, public/build/, and node_modules/. An unexcluded run produces inflated, misleading baselines on day one and destroys trust in the numbers.Sequencing recommendation
Pilot → bake-off vs. upstream → non-gating CI artifact → baseline + named metric owner → single-metric gate → dashboard. Compress steps 1–2 into one sprint; do not skip the bake-off.
Maintenance
phploc as a replaceable commodity. Keep the CI invocation thin — one script, one output path, no bespoke parsing baked into a dozen jobs. If the fork stalls, swapping to sebastianbergmann/phploc or phpmetrics should be a one-file change. A TPM should ask for that abstraction explicitly.Support
phploc guidance is adjacent-but-not-exact. Budget an hour of engineer time to reconcile docs, and don't be surprised by stale command flags (--names and --names-exclude were removed in 7.0.0 in favour of --suffix/--exclude).Scaling
app/, routes/, database/, tests/ as separate invocations rather than the repo root. This keeps runs fast, keeps vendor noise out, and produces more legible per-area trends.memory_limit in the CI step is usually sufficient.Failure modes to watch
phploc as a conversation starter and trend line, never as a performance or quality verdict.php-file-iterator vs. PHPUnit) — the most probable operational failure, and the cheapest to pre-empt with a composer why-not check.--exclude, produces plausible-looking but wrong output. There is no error surface that says "I skipped 40 files." Reconcile the reported file count against find app -name '*.php' | wc -l on the first run and whenever exclusions change.--log-xml/--log-json if available, and pin the version regardless.Ramp-up
How can I help you explore Laravel packages today?