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

Phploc Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

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."
  • The tool's value proposition is exactly what a TPM needs for tech-debt conversations: LOC/CLOC/NCLOC/LLOC, class and method length distribution, cyclomatic complexity per class and method, and structural counts. These are trend metrics, not pass/fail metrics, and they translate well into a debt dashboard or a quarterly maintainability review.
  • Because it is a dev-only CLI binary, it has zero runtime footprint on the Laravel application. That makes the blast radius of adoption very small — the main risk is not "will it break the app" but "will it survive as a dependency."

Integration feasibility

  • Mechanically easy: composer require --dev cmgmyr/phploc and invoke vendor/bin/phploc from a CI job or a local script. No credentials, no services, no database.
  • The important caveat is that the documented path is 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.
  • Text output is human-first. Historically this tool family supported XML/CSV/JSON logging, but the README provided here documents only the plain-text table. A TPM should treat "can we get machine-readable output in this fork" as an open question, because a raw text table means brittle downstream parsing if the goal is a dashboard.

Technical risk (this is the dominant dimension)

  • Fork risk is the headline. This is Chris Gmyr's 2024+ fork of Sebastian Bergmann's long-standing 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.
  • Adoption signals are weak. 27 stars, 0 dependents, three contributors. There is no downstream population that would notice or fix a regression. Combined with a single primary maintainer, this is a bus-factor-1 dependency with no community backpressure.
  • Dependency-constraint churn is a warning sign, not a fatal one. The changelog shows rapid constraint edits: ^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.
  • Metadata hygiene. The release date is listed as 2026-08-31 while the changelog and release notes top out at 8.0.8. A future-dated release is either a feed artifact or a supply-chain signal; either way a TPM should require the team to verify actual tags on Packagist/GitHub before pinning.
  • Parser coverage risk. 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.
  • License is clean — BSD-3-Clause, same as upstream. Legal review should be quick.

Key questions to put to engineering before approval

  1. Is the goal local developer insight, CI gating, or a tracked debt metric over time? Only the third justifies parsing work, and only the second justifies threshold tuning.
  2. Does 8.0.8's 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?
  3. Does the fork still emit XML/CSV/JSON via --log-*, or is the output text-only? (Determines whether the dashboard story is cheap or expensive.)
  4. Do we accept 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.
  5. Who owns the numbers? A metric with no named owner decays into a number nobody reads within two quarters.

Integration Approach

Stack fit

  • Fits a standard Laravel stack cleanly at the tooling tier: PHP CLI + Composer + any CI runner (GitHub Actions, GitLab CI, Jenkins, Bitbucket). No runtime coupling to Laravel, Octane, queues, or storage.
  • Belongs in require-dev only. It must not appear in the production image or the deploy artifact — treat it as a linting-class tool.
  • Natural neighbours in a Laravel repo: PHPStan/Larastan, PHP_CodeSniffer/Pint, PHPUnit/Pest, and 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

  1. Pilot in one repo, one branch. 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.
  2. Run a bake-off against the alternative. Same repo, same commit: upstream 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.
  3. Promote to CI as non-gating. Week one to four: publish the report as a build artifact. No thresholds, no failures. This is the step that reveals parser errors and exclusion mistakes without blocking anyone.
  4. Then, and only then, gate. Pick one metric — realistically a complexity ceiling on changed files, or a total-LLOC budget — and gate PRs on regression against the baseline. Resist gating on five metrics at once.

Compatibility considerations

  • Version constraint: 8.0.1 relaxed PHP to ^7.4 || ^8.0. Confirm actual behaviour on your current PHP 8.2/8.3 runtime — the constraint says "allowed," not "tested."
  • The 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.
  • Pin exactly (8.0.8, no caret) and commit the lockfile. In a fork with 0 dependents, "latest" is not a safety property.
  • Exclusions matter more than flags: default runs will sweep 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.

Operational Impact

Maintenance

  • Low effort to maintain (it's a dev dependency that rarely changes) but elevated ownership risk: one primary maintainer, 27 stars, 0 dependents, and a release history consisting almost entirely of dependency bumps and one revert. There is no upstream contributor pipeline to inherit if the maintainer steps away.
  • Concrete mitigation: treat 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.
  • Legal/licensing: BSD-3-Clause, permissive, attribution-only. Expect no friction.

Support

  • There is no Laravel-specific documentation and no support channel beyond GitHub issues on a low-traffic fork. Helpful consequence for planning: you cannot escalate, so you must be able to live without fixes.
  • Because the namespace diverged, most online 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

  • Analysis is token-based and single-process. On a large Laravel monorepo (thousands of files), expect runtimes that are acceptable in CI but not pleasant locally — minutes, not seconds. There is no parallelism and there are no incremental/cached runs, so it re-analyses the whole tree every time.
  • Scope it deliberately: analyse 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.
  • Watch PHP memory limits on very large trees; a raised memory_limit in the CI step is usually sufficient.

Failure modes to watch

  • False precision. Cyclomatic complexity and LLOC are proxies. Teams will argue with the numbers, and they'll sometimes be right. Position phploc as a conversation starter and trend line, never as a performance or quality verdict.
  • Dependency conflict at install time (php-file-iterator vs. PHPUnit) — the most probable operational failure, and the cheapest to pre-empt with a composer why-not check.
  • Silent under-analysis. Syntax the analyser doesn't recognise, or an over-broad --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.
  • Parsing brittleness. If the dashboard consumes the text table, a patch release that shifts column widths or reorders sections breaks the pipeline silently. Push for --log-xml/--log-json if available, and pin the version regardless.
  • Supply-chain hygiene. The future-dated release entry is the kind of anomaly that should trigger a verification step (confirm tags on GitHub/Packagist) rather than quiet acceptance. Cheap to check, expensive to assume.
  • Threshold gaming. Once complexity is gated, expect classes to be split in ways that satisfy the metric without improving design. Counter by gating only new and modified files, and by pairing the metric with human review.

Ramp-up

  • Running it: near-zero. One composer command, one CLI invocation. A mid-level engineer is productive in under 30 minutes.
  • Interpreting it: moderate. Reading "Average Complexity per Class 19.60" as good or bad requires judgement and a baseline for your own codebase — there is no universal target, and the tool offers no guidance. This is where TPMs most often under-invest.
  • Operationalising it: the real cost. Choosing thresholds, wiring CI, keeping exclusions correct, and sustaining attention over quarters is the work. Assign a named owner (typically a tech lead or staff engineer), define the review cadence up front — quarterly is realistic, per-PR is not — and pre-commit to what happens when a threshold is breached. Without that, adoption produces one impressive report, one enthusiastic Slack thread, and then silence.
  • Recommendation: approve as a low-commitment, non-gating dev tool for a single-quarter pilot, with the explicit understanding that the fork itself is a replaceable commodity and that the deliverable is a habit of measuring, not this particular binary.
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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log