szepeviktor/phpstan-wordpress
PHPStan rules and stubs tailored for WordPress projects. Adds accurate type information for core functions, hooks, and globals to catch bugs earlier and improve static analysis in plugins and themes. Easy to integrate into existing PHPStan setups.
Installation Add the package to your project via Composer:
composer require --dev szepeviktor/phpstan-wordpress
Ensure phpstan/extension-installer is also installed (recommended for auto-loading extensions):
composer require --dev phpstan/extension-installer
Configure PHPStan
Add the extension to your phpstan.neon:
includes:
- vendor/szepeviktor/phpstan-wordpress/extension.neon
Run PHPStan Execute a basic analysis on your WordPress project:
vendor/bin/phpstan analyse src
(Replace src with your WordPress theme/plugin root directory.)
Run PHPStan on a file using WordPress functions (e.g., get_posts()):
vendor/bin/phpstan analyse path/to/your-theme
The extension will now:
wp_query(), get_option()).get_posts()).query_posts()).Theme/Plugin Structure Organize your project with:
/src
/Classes # Business logic
/Templates # Template files (PHP)
/Functions.php # Core functions
Run PHPStan on /src:
vendor/bin/phpstan analyse src --level=5
Template Files
For .php templates (e.g., template-parts/content.php), use:
vendor/bin/phpstan analyse path/to/templates --level=3
(Lower level for templates due to dynamic content.)
Add to .github/workflows/phpstan.yml:
- name: Run PHPStan
run: vendor/bin/phpstan analyse src --level=5
Add Custom Rules
Create a custom extension in phpstan.neon:
extends:
- vendor/szepeviktor/phpstan-wordpress/extension.neon
- custom-rules.neon
Example custom-rules.neon:
services:
- Szepeviktor\PhpStanWordPress\Rules\CustomRule
Mocking WordPress Globals
Use phpstan-wordpress's built-in globals (e.g., $wpdb, $post) without errors:
// No error: $wpdb is recognized as a global.
global $wpdb;
$wpdb->get_var("SELECT * FROM wp_posts");
Validate Hook Callbacks PHPStan will check if callbacks match expected signatures:
add_action('wp_enqueue_scripts', function() { // ✅ Valid
wp_enqueue_style('custom', 'style.css');
});
add_action('wp_enqueue_scripts', 'nonexistent_function'); // ❌ Error: Function not found
Filter Validation Ensure filters return correct types:
add_filter('the_content', function($content) {
return $content . '<p>Modified</p>'; // ✅ Returns string
});
| Issue | Solution |
|---|---|
| False Positives | Use @var annotations for dynamic WordPress objects (e.g., $post). |
Example: /** @var WP_Post */ $post = get_queried_object(); |
|
| Unrecognized Globals | Ensure extension.neon is included in phpstan.neon. |
| Deprecated Functions | Configure error level for deprecations in phpstan.neon: |
| ```neon | |
| errorLevel: 5 | |
| checkDeprecated: true | |
| ``` | |
| Template File Analysis | Lower PHPStan level (e.g., --level=3) for templates with dynamic code. |
Verbose Output
Run with -v for detailed errors:
vendor/bin/phpstan analyse src -v
Ignore Specific Errors
Use @Suppress in code:
// @Suppress("Szepeviktor\PhpStanWordPress\Rules\DeprecatedFunction")
query_posts('showposts=5');
Check Extension Coverage Verify supported WordPress functions in the package docs.
Excluding Files
Ignore node_modules or vendor in phpstan.neon:
excludeFiles:
- node_modules/**
- vendor/**
Custom WordPress Paths
If WordPress is not in the root, set wordpressRoot in extension.neon:
parameters:
wordpressRoot: /path/to/wordpress
Performance
Cache results with --generate-report:
vendor/bin/phpstan analyse src --generate-report=report.html
Add New Rules
Extend Szepeviktor\PhpStanWordPress\Rules\WordPressRuleset in your custom extension.
Override Defaults
Reconfigure parameters in extension.neon:
parameters:
checkHooks: true
checkFilters: true
checkGlobals: true
Community Rules Contribute to the package by adding support for missing WordPress functions via PRs.
How can I help you explore Laravel packages today?