Install
$ agentstack add skill-lonsdale201-wp-agent-skills-wp-phpstan-static-analysis ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
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:
- Rule levels:
- The baseline:
- WordPress stubs:
- WooCommerce stubs:
- Extension installer:
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Lonsdale201
- Source: Lonsdale201/wp-agent-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.