szepeviktor/phpstan-wordpress

WordPress extensions for PHPStan

Fund package maintenance!
szepeviktor

Installs: 3 529 817

Dependents: 586

Suggesters: 20

Security: 0

Stars: 270

Watchers: 12

Forks: 27

Open Issues: 11

Type:phpstan-extension


README

Important

Hello everyone! This is Viktor who runs this PHPStan extension. I am planning to stop contributing to the WordPress ecosystem because it is extremely difficult and no one asks me to join his team as I am a thinker, a devops person, a tool maker (not a builder).

Please support my work to avoid abandoning this package.

Sponsor

Thank you!

WordPress Extensions for PHPStan

Packagist stats Packagist Tweet Build Status PHPStan

Static analysis for the WordPress ecosystem.

Features

  • Enables PHPStan to analyze WordPress plugins and themes.
  • Loads the php-stubs/wordpress-stubs package.
  • Provides dynamic return type extensions for functions that are not covered in php-stubs/wordpress-stubs
  • Defines some WordPress core constants.
  • Validates optional docblocks before apply_filters() and do_action() calls, treating the type of the first @param as definitive.

Requirements

  • PHPStan 2.0 or higher
  • PHP 7.4 or higher (tested up to PHP 8.3)

Installation

To use this extension, require it in Composer:

composer require --dev szepeviktor/phpstan-wordpress

If you also install phpstan/extension-installer then you're all set!

Manual Installation

If you don't want to use phpstan/extension-installer, include extension.neon in your project's PHPStan config:

includes:
    - vendor/szepeviktor/phpstan-wordpress/extension.neon

Configuration

No additional setup is needed. 😃 Just configure PHPStan - for example - as shown below:

parameters:
    level: 5
    paths:
        - plugin.php
        - inc/

For more details, visit the PHPStan Config Reference.

💡 Use the Composer autoloader or a custom autoloader!

Usage

Run the analysis with:

vendor/bin/phpstan analyze

then fix an error and GOTO 10!

You find further information in the examples directory, e.g. examples/phpstan.neon.dist

Usage in WooCommerce Webshops

Refer to WooCommerce Stubs for specific guidance.

Usage of an apply_filters() Docblock

The WordPress ecosystem often uses PHPDoc docblocks in a non-standard way to document parameters passed to apply_filters(). Here’s an example:

/**
 * Filters the page title when creating an HTML drop-down list of pages.
 *
 * @param string  $title Page title.
 * @param WP_Post $page  Page data object.
 */
$title = apply_filters( 'list_pages', $title, $page );

This extension reads these docblocks and instructs PHPStan to treat the filter’s return type as certain, based on the first @param tag. In this example, PHPStan interprets $title as string.

For best results, ensure the first @param tag in these docblocks is accurate.

Make Your Code Testable

  • Write clean OOP code: 1 class per file, and no additional code outside class Name { ... }.
  • Use consistent class naming (WPCS or PSR-4) and store classes in a dedicated inc/ directory.
  • Add precise PHPDoc blocks to classes, properties, methods, functions, and apply_filters() calls.
  • Choose your main plugin file parts.
  • Avoid using core constants, use core functions.
  • Avoid bad PHP practices, such as:
    • functions: eval, extract, compact, list
    • type juggling: $a = '15'; if ($a) ...
  • If you need robust code try avoiding all kinds of type juggling (e.g. if needs a boolean), see Variable handling functions
  • Avoid enabling exit_error in WP_CLI::launch or WP_CLI::runcommand for improved testability.

Dirty Corner (FAQ)

WordPress uses conditional function and class definition to allow overrides. Use sed command to exclude function stubs when they are previously defined.

sed -i -e 's#function is_gd_image#function __is_gd_image#' vendor/php-stubs/wordpress-stubs/wordpress-stubs.php