Linting is the process of using software to analyze static code for programming errors and bugs, code smells, and stylistic errors. Code smells are simply characteristics or constructs that may present as errors during program execution. Generically, the term lint (or linter) refers to a class of programs that perform these functions prior to or as part of compiling, however, it originates from a specific program named ‘lint’ used for evaluating C code.
This guide is focused on linting PHP code against the WordPress Coding Standards using PHP_CodeSniffer (phpcs and phpcbf). For those who want to publish plugins or themes as part of the official WordPress.org directory, linting your code against the WordPress Coding Standards significantly reduces the repeated back-and-forth issue correction cycle in the overall approval process.
Although I am using a Windows machine to install and run the development environment, all of the referenced applications are available on most major operating systems and the listed commands are not operating system specific.
Step 1 – Install PHP
PHP is a prerequisite for installing Composer in the next step. While you can download and install PHP as a standalone product, I prefer to install XAMPP which is a free Apache distribution containing PHP, MySQL (MariaDB), and several other products. The primary advantage of using XAMPP is that it creates an all-in-one local development and testing environment to install and execute WordPress and custom code. For the purposes of this guide, the subsequent steps only require access to PHP so either standalone PHP or XAMPP is sufficient. If you do install XAMPP, it does not need to be actively running for the other steps to work properly.
In this example, XAMPP is installed in the
c:\xampp\ directory and PHP is located in the
After installing either option, verify that the PHP directory is included in the
Step 2 – Install Composer
Composer is an application-level dependency management application for PHP. In other words, Composer handles the installation and update of your PHP project dependencies and libraries. Composer will be used to install PHP_CodeSniffer, WordPress Coding Standards, and PHPCompatibilityWP in subsequent steps.
To get started, download and install Composer. As part of the installation process, ensure Composer is able to locate the command line PHP (
php.exe) program installed during Step 1. Since I used XAMPP, Composer is configured to use
php.exe located in the
After installing Composer, verify that the
Composer\vendor\bin directory is included in the
For those with Composer already installed, execute the following command to update the Composer application itself as well as any dependencies.
composer self-update && composer global update
These commands result in the following output (or similar). Since I executed these commands on a fresh install of Composer, there is nothing to update. No dependencies have been installed at this point so the
composer.json file does not yet exist.
You are already using the latest available Composer version 2.4.3 (stable channel). Changed current directory to C:/Users/john/AppData/Roaming/Composer Composer could not find a composer.json file in C:\Users\john\AppData\Roaming\Composer To initialize a project, please create a composer.json file. See https://getcomposer.org/basic-usage
When the update commands are executed after installing dependencies, the output will be similar to the following.
You are already using the latest available Composer version 2.4.3 (stable channel). Changed current directory to C:/Users/john/AppData/Roaming/Composer Loading composer repositories with package information Updating dependencies Nothing to modify in lock file Installing dependencies from lock file (including require-dev) Nothing to install, update or remove Generating autoload files No security vulnerability advisories found
NOTE: Even though we have not installed any dependencies yet, the following commands are provided for reference if you ever need to remove the dependencies installed as part of this guide.
composer global remove dealerdirect/phpcodesniffer-composer-installer composer global remove wp-coding-standards/wpcs composer global remove phpcompatibility/phpcompatibility-wp
Step 3 – Install PHP_CodeSniffer
composer global require --dev dealerdirect/phpcodesniffer-composer-installer
If prompted “Do you trust “dealerdirect/phpcodesniffer-composer-installer” to execute code and wish to enable it now?“, then respond ‘
y‘ to proceed.
Changed current directory to C:/Users/john/AppData/Roaming/Composer Info from https://repo.packagist.org: #StandWithUkraine Using version ^0.7.2 for dealerdirect/phpcodesniffer-composer-installer ./composer.json has been created Running composer update dealerdirect/phpcodesniffer-composer-installer Loading composer repositories with package information Updating dependencies Lock file operations: 2 installs, 0 updates, 0 removals - Locking dealerdirect/phpcodesniffer-composer-installer (v0.7.2) - Locking squizlabs/php_codesniffer (3.7.1) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 2 installs, 0 updates, 0 removals - Installing squizlabs/php_codesniffer (3.7.1): Extracting archive dealerdirect/phpcodesniffer-composer-installer (installed globally) contains a Composer plugin which is currently not in your allow-plugins config. See https://getcomposer.org/allow-plugins Do you trust "dealerdirect/phpcodesniffer-composer-installer" to execute code and wish to enable it now? (writes "allow-plugins" to composer.json) [y,n,d,?] y - Installing dealerdirect/phpcodesniffer-composer-installer (v0.7.2): Extracting archive Generating autoload files No security vulnerability advisories found
phpcs -i command displays the installed coding standards.
The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz and Zend
Step 4 – Install WordPress Coding Standards
Now we can install the WordPress Coding Standards ruleset which is used to validate code developed for WordPress against the official WordPress Coding Standards.
Execute the following command.
composer global require --dev wp-coding-standards/wpcs
Changed current directory to C:/Users/john/AppData/Roaming/Composer Using version ^2.3 for wp-coding-standards/wpcs ./composer.json has been updated Running composer update wp-coding-standards/wpcs Loading composer repositories with package information Updating dependencies Lock file operations: 1 install, 0 updates, 0 removals - Locking wp-coding-standards/wpcs (2.3.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Installing wp-coding-standards/wpcs (2.3.0): Extracting archive Generating autoload files PHP CodeSniffer Config installed_paths set to ../../wp-coding-standards/wpcs No security vulnerability advisories found
phpcs -i command displays the installed coding standards which now include WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra.
The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra
Step 5 – Install PHPCompatibilityWP
The final dependency to install is PHPCompatibilityWP which is used to check for PHP cross-version compatibility issues.
composer global require --dev phpcompatibility/phpcompatibility-wp
Changed current directory to C:/Users/john/AppData/Roaming/Composer Info from https://repo.packagist.org: #StandWithUkraine Using version ^2.1 for phpcompatibility/phpcompatibility-wp ./composer.json has been updated Running composer update phpcompatibility/phpcompatibility-wp Loading composer repositories with package information Updating dependencies Lock file operations: 3 installs, 0 updates, 0 removals - Locking phpcompatibility/php-compatibility (9.3.5) - Locking phpcompatibility/phpcompatibility-paragonie (1.3.1) - Locking phpcompatibility/phpcompatibility-wp (2.1.3) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 3 installs, 0 updates, 0 removals - Installing phpcompatibility/php-compatibility (9.3.5): Extracting archive - Installing phpcompatibility/phpcompatibility-paragonie (1.3.1): Extracting archive - Installing phpcompatibility/phpcompatibility-wp (2.1.3): Extracting archive 3 package suggestions were added by new dependencies, use `composer suggest` to see details. Generating autoload files PHP CodeSniffer Config installed_paths set to ../../phpcompatibility/php-compatibility,../../phpcompatibility/phpcompatibility-paragonie,../../phpcompatibility/phpcompatibility-wp,../../wp-coding-standards/wpcs No security vulnerability advisories found
phpcs -i command displays the installed coding standards which now include PHPCompatibility, PHPCompatibilityParagonieRandomCompat, PHPCompatibilityParagonieSodiumCompat, and PHPCompatibilityWP.
The installed coding standards are MySource, PEAR, PSR1, PSR2, PSR12, Squiz, Zend, PHPCompatibility, PHPCompatibilityParagonieRandomCompat, PHPCompatibilityParagonieSodiumCompat, PHPCompatibilityWP, WordPress, WordPress-Core, WordPress-Docs and WordPress-Extra
Step 6 – PHP_CodeSniffer Custom Ruleset
All of the installation steps are complete and we can finally begin linting code. First, we need to configure PHP_CodeSniffer with the appropriate flags and rules for the project. To do this, we create a file named
phpcs.xml in the root folder of a PHP project. A sample
phpcs.xml file is provided below which should be customized for your specific project needs. In this example configuration, PHP_CodeSniffer evaluates the project’s PHP files against the WordPress Coding Standards ruleset with a few rule exclusions. Yes, I realize I have mostly excluded Commenting rules so shame on me. The configuration file also instructs the sniffer to evaluate the code for PHP compatibility against PHP version 7.4 or later. Again, adjust the configuration file to meet your needs.
<?xml version="1.0"?> <ruleset name="DALESANDRO.NET Coding Standards"> <description>Custom coding standards configuration for WordPress plugin development.</description> <!-- PHPCS flags: n: Do not print warnings. s: Show sniff codes in all reports. p: Show progress of the run. --> <arg value="nsp"/> <!-- Check all files in the current local directory and all subdirectories. --> <file>.</file> <!-- Check files with PHP extensions only. --> <arg name="extensions" value="php"/> <!-- Use colors in output. --> <arg value="-colors"/> <!-- Include WordPress Coding Standards. --> <rule ref="WordPress"> <!-- Exclude the following rules. --> <exclude name="Squiz.Commenting.ClassComment.Missing"/> <exclude name="Squiz.Commenting.FileComment.Missing"/> <exclude name="Squiz.Commenting.FileComment.MissingPackageTag"/> <exclude name="Squiz.Commenting.FunctionComment.Missing"/> <exclude name="Squiz.Commenting.VariableComment.Missing"/> <exclude name="WordPress.WP.DeprecatedFunctions.sanitize_urlFound"/> <exclude name="WordPress.WP.EnqueuedResourceParameters.MissingVersion"/> <exclude name="WordPress.Security.NonceVerification.Missing"/> </rule> <rule ref="PHPCompatibilityWP"/> <config name="testVersion" value="7.4-"/> <config name="minimum_supported_wp_version" value="5.9"/> </ruleset>
As a test, I have created a project directory named
c:\test. In this directory,
phpcs.xml is located at the root level with a subdirectory named
classes. A PHP file named
class-test.php is found within the
c:\test\ ├── phpcs.xml └── classes/ └── class-test.php
At a command prompt, executing
phpcs . from within the parent project directory results in the following sample output. We can see that the code is evaluated against the WordPress Coding Standards based on the various WordPress.DB and WordPress.Security rules flagged as errors. The output includes color as directed in the configuration file.
As I mentioned earlier in this guide, PHP_CodeSniffer includes a second script named phpcbf. This script is used to automatically fix code formatting and style inconsistencies. I have created another sample file named
class-test2.php which is formatted by someone who both dislikes indentation and does not have a functioning space bar.
At a command prompt, executing
phpcbf class-test2.php results in the code being formatted according to conventional coding style guidelines.