Wp phpstan static analysis
Skill Lonsdale201/wp-agent-skills/dev-tooling/wp-phpstan-static-analysis
Run PHPStan static analysis on a WordPress plugin or theme using `szepeviktor/phpstan-wordpress`. Covers the composer dev-dependencies and what is pulled transitively (`phpstan/phpstan` ^2.0, `php-stubs/wordpress-stubs`), the optional `phpstan/extension-installer` that auto-registers the extension, the `phpstan.neon.dist` config (level 0-10 / `max`, `paths`, the `vendor/szepeviktor/phpstan-wordpress/extension.neon` include when not using the installer), why WordPress needs stubs, adding WooCommerce stubs (`php-stubs/woocommerce-stubs`) for cross-plugin analysis, the `--generate-baseline` workflow for legacy code, common WP false positives the extension fixes (apply_filters arg counts, is_wp_error narrowing, hook callbacks, dynamic constants), and running with `--level` / `--memory-limit`. Use when adding static analysis, writing phpstan.neon, raising the level, or taming WP-specific PHPStan errors.From its SKILL.md
npx -y skills add Lonsdale201/wp-agent-skills --skill wp-phpstan-static-analysisAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as GPLv2-or-later. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
8.7 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it
PHPStan static analysis for WordPress
PHPStan catches type errors, dead code, and bad calls without running anything. It doesn't load WordPress, so it needs stubs for core's functions/classes — szepeviktor/phpstan-wordpress provides those plus WP-aware rules. This skill wires it up and tames the WP-specific noise. PHPCS (wp-phpcs-coding-standards) covers style; PHPStan covers types/logic — run both.
When to use this skill
- Adding static analysis to a plugin/theme.
- Writing or reviewing
phpstan.neon/phpstan.neon.dist. - Raising the analysis level on existing code (and baselining the backlog).
- Killing WP-specific false positives (
apply_filtersarg counts,is_wp_error(),$wpdb, conditional constants).
Install
composer require --dev szepeviktor/phpstan-wordpress
composer require --dev phpstan/extension-installer # recommended: auto-registers the extension
szepeviktor/phpstan-wordpress (2.0.3) pulls in phpstan/phpstan ^2.0 and php-stubs/wordpress-stubs transitively — you don't add those yourself. It requires PHPStan 2.0+.
phpstan/extension-installer is a Composer plugin that auto-includes any installed phpstan-extension package's config, so you don't hand-wire the include. Composer 2.2+ needs it in allow-plugins:
{
"config": {
"allow-plugins": {
"phpstan/extension-installer": true
}
}
}
Configure (phpstan.neon.dist)
With extension-installer, the config is minimal — the extension auto-registers:
parameters:
level: 5
paths:
- my-plugin.php
- includes/
Without extension-installer, include the extension manually (exact path, verified):
includes:
- vendor/szepeviktor/phpstan-wordpress/extension.neon
parameters:
level: max
paths:
- my-plugin.php
- includes/
ignoreErrors:
# WP filter functions use func_get_args(); calling with extra args is fine.
- '#^Function apply_filters(_ref_array)? invoked with [34567] parameters, 2 required\.$#'
You normally do not set bootstrapFiles for WP core — the extension already loads php-stubs/wordpress-stubs. Add bootstrapFiles only for extra stubs (see WooCommerce below) or your own define-shims.
Levels
PHPStan has levels 0–10 (0 loosest, 10 strictest; level 10 was added in PHPStan 2.0). max is an alias for the highest. Start where the code passes (often 5), commit that, then raise one level at a time. Don't jump to max on a legacy plugin — baseline instead (below).
Stubs, and cross-plugin analysis
PHPStan can't see WordPress, so wordpress-stubs supplies typed, implementation-free declarations of core functions/classes. The package is versioned to the WordPress version it was generated from.
To analyze code that calls another plugin's API (e.g. WooCommerce), add that plugin's stubs and register them:
composer require --dev php-stubs/woocommerce-stubs
parameters:
bootstrapFiles:
- vendor/php-stubs/woocommerce-stubs/woocommerce-stubs.php
php-stubs/woocommerce-stubs depends on wordpress-stubs, so WP stubs come along. Without the right stubs, PHPStan reports "unknown function/class" for every external call.
The baseline workflow (legacy code)
Don't fight thousands of pre-existing errors. Snapshot them and only gate new/changed code:
vendor/bin/phpstan analyse --generate-baseline
This writes phpstan-baseline.neon (every current error). Include it:
includes:
- phpstan-baseline.neon
Now CI is green, but any new error fails the build. Over time, fix entries and regenerate a smaller baseline, or raise the level behind the baseline. This is how you adopt PHPStan (or a higher level) on an existing plugin without a giant rewrite.
WP-specific false positives the extension handles
phpstan-wordpress already fixes the usual WordPress noise — don't suppress these by hand:
apply_filters()"invoked with N parameters, 2 required" — WP filters usefunc_get_args(); the bundledignoreErrorsregex (above) covers it.- Loose return types — dynamic return-type extensions narrow
apply_filters(),esc_sql(),wp_parse_url(),shortcode_atts(),wp_slash(), and more. is_wp_error()narrowing — afterif ( is_wp_error( $x ) ), PHPStan knows$xis aWP_Error(vs the success type) in each branch.- Hook callbacks —
HookCallbackRulevalidatesadd_action()/add_filter()callback signatures;HookDocsRulevalidates the docblocks onapply_filters()/do_action()calls. - WordPress constants — the extension's
dynamicConstantNameslist (WP_DEBUG,WP_DEBUG_LOG,WP_DEBUG_DISPLAY,SCRIPT_DEBUG,ABSPATH,WP_CONTENT_DIR,WP_PLUGIN_DIR, …) plus itsWpConstantFetchRuletell PHPStan those WordPress constants may be conditionally (re)defined, so it won't wrongly narrowif ( WP_DEBUG )-style checks. - Early-terminating functions —
wp_send_json*andwp_nonce_aysare known to end execution, so PHPStan won't flag "undefined variable after" them.
One it can't infer for you: global $wpdb;. Annotate it where used:
global $wpdb;
/** @var \wpdb $wpdb */
Run it
vendor/bin/phpstan analyse # uses phpstan.neon(.dist)
vendor/bin/phpstan analyse -l 8 includes/ # override level + path
vendor/bin/phpstan analyse --memory-limit 1G # large plugins + stubs eat RAM
Add a composer script so it joins the QA entry point alongside phpcs/phpunit:
"scripts": {
"analyze": "phpstan analyse"
}
Critical rules
- Install
szepeviktor/phpstan-wordpress(it brings PHPStan 2.0 + WP stubs) — don't hand-assemble stubs. - Use
phpstan/extension-installer(andallow-plugins) so the extension auto-registers; otherwise add theextension.neoninclude manually. - Pick a level the code passes, commit, raise gradually.
maxon legacy code without a baseline is noise, not signal. - Baseline legacy errors with
--generate-baselineso only new/changed code is gated. - Add the right stubs for cross-plugin calls (e.g.
php-stubs/woocommerce-stubs) or every external symbol is "unknown". - Don't suppress the known WP patterns by hand — the extension already handles
apply_filtersarg counts,is_wp_error(), hooks, constants. Annotateglobal $wpdbwith/** @var \wpdb $wpdb */.
Cross-references
- Run
wp-phpcs-coding-standardsfor the complementary style/standards gate (PHPCS = style, PHPStan = types/logic). - Run
wp-phpunit-test-setupto add PHPStan to the same composer scripts and CI matrix. - Run
wp-plugin-architecturewhen PHPStan findings point at structural issues (untyped boundaries, god objects). - Run
wp-security-audit— PHPStan catches type bugs, not security ones; pair them.
References
- phpstan-wordpress: https://github.com/szepeviktor/phpstan-wordpress
- Rule levels: https://phpstan.org/user-guide/rule-levels
- The baseline: https://phpstan.org/user-guide/baseline
- WordPress stubs: https://github.com/php-stubs/wordpress-stubs
- WooCommerce stubs: https://github.com/php-stubs/woocommerce-stubs
- Extension installer: https://github.com/phpstan/extension-installer
- Related documentation: https://github.com/szepeviktor/phpstan-wordpress/blob/master/extension.neon
- Related documentation: https://github.com/szepeviktor/phpstan-wordpress/blob/master/examples/phpstan.neon.dist
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.