So you want to write WordPress code following modern PHP best practices, adhering to the official (or other established) coding standards? Great! This post jumps right into it.
Disclaimer: Please note that this post is opinionated, and thus brief. However, by no means am I saying that this is the best or even the only way to set up and use this! It is just what works for me (and a lot of other folks), and what is also pretty easy to do, in my opinion. 🙂
This post consists of three parts, which reflect the individual steps to set up modern PHP coding standards:
Managing PHP Dependencies
In order to manage (i.e., install and update) the required PHP dependencies, we make use of Composer, the dependency manager for PHP.
Setting Up Composer
If you are already using Composer (i.e., you have a composer.json
file in your project), you can skip this step. Otherwise, run the following command to create an empty composer.json
file:
composer init -n
Installing PHP_CodeSniffer
Now, we need a tool to check our code against whatever rules we define later on. The de-facto standard for this job is PHP_CodeSniffer.
Install PHP_CodeSniffer:
composer require --dev squizlabs/php_codesniffer
For easy installation of additional rulesets (and some sort of automatic discovery of these), we make use of the PHP_CodeSniffer Composer Installer plugin.
Install PHP_CodeSniffer Composer Installer:
composer require --dev dealerdirect/phpcodesniffer-composer-installer
Installing Additional Rulesets
While PHP_CodeSniffer already comes with a suite of rulesets to choose from, there are (additional) rulesets that are better suited for WordPress development. In this post, we make use of the official WordPress Coding Standards, as well as PHPCompatibilityWP, a WordPress-specific ruleset providing PHP compatibility checks.
Install WordPress Coding Standards:
composer require --dev wp-coding-standards/wpcs
Install PHPCompatibilityWP:
composer require --dev phpcompatibility/phpcompatibility-wp
Final composer.json
File
Your composer.json
file should now look something like this:
{
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.5.0",
"phpcompatibility/phpcompatibility-wp": "^2.0",
"squizlabs/php_codesniffer": "^3.4",
"wp-coding-standards/wpcs": "^2.0"
}
}
If you were using Composer already, you will, of course, have some additional content in your composer.json
file.
Creating a Custom Ruleset
The next step would be to make use of the installed rulesets. Basically, this means that we go ahead and pick whatever rules make sense for our particular project.
This could look like the following (again: simple, on purpose) phpcs.xml.dist
file:
<?xml version="1.0"?>
<ruleset>
<file>src</file>
<file>index.php</file>
<!-- Show progress and sniff codes in all reports. -->
<arg value="ps"/>
<!-- A path to strip from the front of file paths inside reports. -->
<arg name="basepath" value="src"/>
<arg name="colors"/>
<arg name="extensions" value="php"/>
<!-- Check for PHP cross-version compatibility. -->
<config name="testVersion" value="7.2-"/>
<rule ref="PHPCompatibilityWP"/>
<!-- WordPress coding standards. -->
<rule ref="WordPress">
<!-- Exclude as plugin adheres to the PSR-4 standard. -->
<exclude name="WordPress.Files.FileName"/>
</rule>
<!-- Specify custom nonce validation. -->
<rule ref="WordPress.CSRF.NonceVerification">
<properties>
<property name="customNonceVerificationFunctions" type="array" value="validate_nonce" />
</properties>
</rule>
<!-- Allow namespaced hook names in dot notation. -->
<rule ref="WordPress.NamingConventions.ValidHookName">
<properties>
<property name="additionalWordDelimiters" value="."/>
</properties>
</rule>
</ruleset>
The above ruleset assumes a WordPress plugin with an index.php
main plugin file, and the rest of the PHP code living in the src
directory. The configuration includes sniff codes in all reports (which includes the command line output), a progress indicator, and colored output. Only files with the .php
extension will be targeted.
PHP compatibility will be checked for PHP 7.2 and beyond.
The plugin code is checked against the entirety of the WordPress coding standards, minus the default filename check (as the plugin is assumed to follow PSR-4). Two rules, WordPress.CSRF.NonceVerification
and WordPress.NamingConventions.ValidHookName
, have been customized.
Checking the Code
The last step is to actually check our code against the defined standards. And there are plenty ways (and situations) to do so. When and how you do this, might depend on the project, the client, the environment, and your personal preference.
In the end, however, it all boils down to some (local) server running PHP_CodeSniffer with the defined ruleset (specifying the code to check):
./vendor/bin/phpcs
This can be done locally, on demand, automatically inside your IDE on save, automatically on some git hook (e.g., pre-commit), as part of your continuous integration pipeline (e.g., for each commit, or for newly created pull requests), and much much more…
Thanks for your article, really very well. But I found a few mistakes:
1. If you want to use the
PHPCompatibilityWP
add to your config the next code with minimal WordPress version:config name="minimum_supported_wp_version" value="4.9-"
2. argument file doesn’t work with argument basepath. Better use to tag exclude-pattern vendor/* exclude-pattern.
3. For PSR4 better exclude only this rules:
WordPress.Files.FileName.InvalidClassFileName
WordPress.Files.FileName.NotHyphenatedLowercase