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

Phpstan Wordpress Laravel Package

szepeviktor/phpstan-wordpress

PHPStan extension that enables static analysis of WordPress plugins and themes: loads WordPress stubs, adds dynamic return types, defines core constants, and validates apply_filters/do_action docblocks. Requires PHPStan 2.0+ and PHP 7.4+.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the package actually is. szepeviktor/phpstan-wordpress is a PHPStan extension (config fragment + PHP code) that teaches PHPStan about WordPress. It does three jobs:

  1. Pulls in php-stubs/wordpress-stubs so WordPress core functions/classes resolve during static analysis.
  2. Registers dynamic return-type and type-specifying extensions for core functions whose return types are input-dependent (get_sites(), term_exists(), wp_parse_url(), has_filter(), is_wp_error(), the *_slash() family, current_time(), etc.).
  3. Declares core constants as dynamic and validates @param docblocks preceding apply_filters() / do_action(), treating the first @param as the authoritative return type of the filter.

Architecture fit. This is a dev-time only dependency. It ships no runtime code into the WordPress plugin/theme, so it carries zero production attack surface, zero runtime latency, and zero hosting constraint. That is a very favourable risk profile for a TPM: the blast radius of failure is limited to CI and developer laptops. Architecturally it slots into the standard composer.json require-dev + extension.neon include model, which means it composes cleanly with existing PHPStan config, baselines, and level settings rather than competing with them. It is an additive layer on tooling the team already runs or should already be running.

Integration feasibility. Friction is low: one Composer command, and if phpstan/extension-installer is present, literally nothing else. Manual install is a two-line NEON include. Requirements are PHPStan ≥ 2.0 and PHP ≥ 7.4 — both are baseline-modern for any actively maintained WordPress codebase in 2025+. No service account, no secrets, no network egress, no data leaving the build agent. The real work is not installing it; it is adopting it, i.e., triaging the baseline of pre-existing errors it will surface on a legacy plugin.

Technical risk.

  • Bus factor of one, publicly acknowledged. The README opens with the maintainer stating he plans to stop contributing to the WordPress ecosystem and is soliciting sponsorship and/or a team to join. This is the single most important line in the entire artefact. Treat it as a known, scheduled abandonment risk rather than a hypothetical.
  • The "Dirty Corner" workaround. The README documents a sed command that monkey-patches vendor/php-stubs/wordpress-stubs/wordpress-stubs.php to rename conditionally-defined functions. Any recommended workflow that requires mutating a vendored file inside vendor/ is fragile: it breaks on composer update, it is invisible to code review, and it is not reproducible without a wrapper script checked into the repo. This is a genuine engineering-debt marker.
  • Coupling to PHPStan major versions. The extension moved through PHPStan 1.x → 2.0 transitions with real breaking churn (deprecated instanceof usage, version-conditional assert types, moved extensions). A PHPStan major bump is a coordinated upgrade, not a drop-in.
  • Stubs drift. Correctness depends on php-stubs/wordpress-stubs tracking WordPress core. The v2.0.4 release exists purely to widen the stubs version range for 7.0 — evidence that version-range pinning is a recurring maintenance chore.
  • Docblock semantics are a contract. The apply_filters() feature trusts the first @param. If the docblock is wrong, PHPStan will confidently propagate the wrong type and can mask real bugs. This inverts the usual assumption that the analyser is conservative.
  • Data-quality caveats in the source metrics. "Dependents: 0" is almost certainly a measurement artefact (it contradicts a mature, 334-star package with a v2.x line and named contributors from Automattic/WordPress core), and a "last release" dated 2026-08-28 is anomalous relative to the present. Do not use either number in a business case without independent verification.

Key questions for the maintainer / team.

  1. Is there a named successor or co-maintainer, and is a fork-and-steward path agreed if the maintainer steps away?
  2. What is the intended support window after the announced wind-down — security fixes only, PHPStan 3 compatibility, or hard stop?
  3. Can the sed stubs workaround be replaced by an upstream stubs change or a supported config flag?
  4. What is the tested matrix commitment (PHP 8.3 vs 8.4 is inconsistent between README and release notes)?
  5. For us internally: which of our plugins are net-new-code-only gating vs. full-codebase remediation, and who owns the baseline?

Integration Approach

Stack fit. Ideal for any team running WordPress plugins/themes with Composer-managed dev dependencies and a CI pipeline (GitHub Actions, GitLab CI, Bitbucket). It is a quality gate for PHP, sitting alongside PHPCS/WPCS (style) and PHPUnit (behaviour). Position it explicitly as the type-correctness layer, not a replacement for WordPress Coding Standards — WPCS enforces formatting and i18n; this enforces type flow and API misuse.

Recommended topology.

  • Add szepeviktor/phpstan-wordpress and phpstan/phpstan to require-dev at the plugin repository root, not the WordPress install root.
  • Require phpstan/extension-installer to avoid hand-maintained NEON includes per repo.
  • Commit phpstan.neon.dist with level, paths, and includes; keep machine-local overrides in an untracked phpstan.neon.
  • If WooCommerce is in scope, add php-stubs/woocommerce-stubs per the README's pointer — these compose.
  • Pin to a caret range on the minor (^2.0) and lock via composer.lock; treat lockfile bumps as reviewed changes.

Migration path (avoid the "wall of red" failure mode).

  1. Spike on one mid-sized, actively developed plugin. Install, run at level 0, record error count and wall-clock time. This is a one-day investigation.
  2. Baseline the existing debt: vendor/bin/phpstan analyse --generate-baseline. Commit the baseline. This is the crucial political step — it lets the team enforce zero new errors immediately without a freeze on feature work.
  3. Ratchet the level upward over time (0 → 5 → higher) and shrink the baseline monotonically. Do not attempt a big-bang level jump.
  4. Gate CI on changed files first (diff-scoped analysis or reviewdog-style annotations), then on full-repo once the baseline is stable.
  5. Normalise the apply_filters() conventions: because the first @param is treated as definitive, add a review checklist item for hook docblocks. Bad docblocks become actively harmful here.
  6. Roll out to remaining repos via a shared reusable CI workflow, not copy-pasted YAML.

Compatibility notes.

  • Keep a per-repo matrix over PHP versions you actually support; the extension itself supports 7.4+, but your code target drives the matrix.
  • Avoid the sed stubs patch unless strictly required; if required, wrap it in a documented Composer script so it is reproducible and visible.
  • Watch for the conditional function/class definition pattern in WordPress — the reason the workaround exists. Prefer code that does not trigger it.
  • Do not enable WP_CLI::launch's exit_error per the README's testing guidance; it interferes with analysability.

Operational Impact

Maintenance. The steady-state cost is low but non-zero: PHPStan and stubs version bumps arrive several times a year, and each is a small, reviewable dependency PR. Budget roughly one engineer-day per quarter per org, plus the PHPStan major-version migration every ~18–24 months, which is a multi-day coordinated effort across repos. The dominant maintenance item is not the tool; it is baseline hygiene — without a policy that the baseline only shrinks, it silently becomes a permanent suppression file and the investment decays to zero.

Support. Community-only, best-effort, no SLA, no vendor. There is a single primary maintainer who has publicly signalled intent to exit. For an organisation where static analysis is a gating CI check, that is an unacceptable sole-source position unless mitigated. Mitigations, in order of preference: (a) fork to an internal namespace or a team-owned org and vendor it via a private Composer registry; (b) mirror the package internally and pin, accepting delayed updates; (c) accept the risk explicitly because the failure mode is "CI goes red once and you remove one line" rather than a production outage. Option (c) is defensible precisely because this is a dev dependency — that is the key judgement call for a TPM here.

Scaling. Analysis cost grows superlinearly with codebase size and with PHPStan level. Mitigations: enable PHPStan's parallel processing (parallel.maximumNumberOfProcesses), set memory_limit explicitly (PHPStan is memory-hungry at higher levels), split analysis across multiple NEON config files or per-plugin CI jobs rather than one monolith, and cache Composer between runs. At 50+ repos, switch to a reusable workflow with a shared config package so a level bump is one change, not fifty. CI minutes are the real budget line — full-repo analysis at high levels on a large plugin can run into minutes; diff-scoped gating keeps this cheap.

Failure modes to plan for.

Failure Symptom Mitigation
Maintainer abandons No PHPStan 3 support; stubs drift Internal fork / mirror; monitor releases
PHPStan major bump Extension incompat, mass false positives Pin PHPStan; upgrade as a tracked project
Stubs drift vs WP core Unknown function/class errors Keep stubs range wide; bump with WP releases
Bad apply_filters() docblock Wrong type propagated, real bug masked Review checklist; treat hook docblocks as code
sed stubs workaround lost CI passes locally, fails clean Composer script, not tribal knowledge
Baseline never shrinks Metric looks green, code still has debt Enforce monotonic baseline reduction in review

Ramp-up. Developer learning curve is the most underestimated cost. Two distinct skills: (1) PHPStan itself — levels, @phpstan- annotations, generics, baselines, ignoring errors correctly rather than with ignoreErrors carpet-bombing; (2) WordPress-specific typing — WP_Error union handling, filter return types, dynamic constants. Expect 1–2 days per engineer to productive, and designate one "static analysis champion" per team who owns config and triages false positives. Ship a short internal playbook covering: how to fix vs. how to baseline vs. when to file upstream, and the house rule that @param on a filter docblock is a public API contract.

TPM summary. This is a high-leverage, low-cost, low-blast-radius developer-productivity investment with an unusually clean risk profile (dev-only, MIT, no runtime footprint) undermined by a clearly disclosed single-maintainer sustainability problem and one fragile vendor-patching workaround. Recommended posture: adopt, but own your exit — internal fork or mirror as a contingency, baseline-plus-ratchet as the rollout pattern, and explicit acceptance that the worst case is a stalled CI gate rather than a broken product.

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.
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support