WordPress Coding Standards(WPCS) for PHP

18 mins
200

WordPress Coding Standards(WPCS) the list of PHP_CodeSniffer (PHPCS) ruleset (sniffs) to check your code inside WordPress. It can improve your code quality and adhere to basic code conventions for WordPress.

Do you work in a team or just want to upgrade a code quality? Then you need to think about a single coding standard. I’m afraid you but if in your team more then one person it doesn’t work without quality control tools. The control quality tool for coding standard names the linter and exists for each programming language.

Lint, or a linter, is a static code analysis tool used to flag programming errors, bugs, stylistic errors, and suspicious constructs.

Wikipedia

As example for Python – Pylint, for PHP – PHP_CodeSniffer, for JavaScript – ESLint or JSHint, etc.

The WordPress Coding Standard includes simple rules about spaces and blanks as harder security rules, caching, and etc.

How to install WPCS?

Just use the composer:

composer require wp-coding-standards/wpcs --dev

When you add any packages for PHP_CodeSniffer you need to add these packages to the scope of PHPCS. The best solution is a package that automatically adds all packages from your vendor in the scope of PHPCS.

composer require dealerdirect/phpcodesniffer-composer-installer --dev

And now you can easy to check the file and fix it:

vendor/bin/phpcs --standard=WordPress path/to/some/file.php 
vendor/bin/phpcbf --standard=WordPress path/to/some/file.php 

How to setting the PHPStorm?

PHPStorm -> Settings -> Languages & Frameworks -> PHP -> CLI Interpreter and choose the current PHP version.

PHPStorm -> Settings -> Languages & Frameworks -> PHP -> Quality Tools -> PHP_CodeSniffer -> Configuration and click on ‘‘ button

Fill the PHP_CodeSniffer path:

path/to/vendor/squizlabs/php_codesniffer/bin/phpcs

and fill the Path to phpcbf:

path/to/vendor/squizlabs/php_codesniffer/bin/phpcsbf

Press on Validate button and accept that your paths are correct.

PHPStorm -> Settings -> Editor -> Inspection -> Quality Tools -> PHP_CodeSniffer validation:

Checked Show sniff name

In the Coding Standard list, you can see the next packages: WordPress, WordPress-Core, WordPress-Docs, WordPress-Extra. Choose WordPress and save it.

If you violate coding standards, in the editor, the lines will be underlined. If you hover over the underlined line, you will see an error.

As example:

phpcs: WordPress.Security.NonceVerification.Missing: Processing form data without nonce verification.

Where WordPress.Security.NonceVerification.Missing – sniff name and Processing form data without nonce verification. – description.

How to ignore some rules?

Sometimes your code can’t fully compatibility with WPCS. As example:

global $wpdb;
$id       = 15;
$my_query = $wpdb->get_results( 'SELECT name FROM my_table WHERE id=' . $id );

In this example a few notices:

  • WordPress.DB.PreparedSQL.NotPrepared
  • WordPress.DB.DirectDatabaseQuery.NoCaching
  • WordPress.DB.DirectDatabaseQuery.DirectQuery

Raw data is a potential XSS backdoor. We can fix this with $wpdb->prepare, cache some queries is also great for performance, but what do you need to do with a direct query? The right way is adding the ignore rule, but it is very important to understand the reason. If you add an ignore rule, you can read it as a developer’s signature about that line.

global $wpdb;
$id       = 15;
$my_query = wp_cache_get( 'my_query' );
if ( ! $my_query ) {
	$my_query = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
		$wpdb->prepare( 'SELECT name FROM my_table WHERE id=%d', $id )
	);
	wp_cache_set( 'my_query', $my_query );
}

phpcs:ignore – is ignoring the next line of your code. The best practice you’re php:ignore with the rule description phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery. So we ignoring only one rule from our coding standard. Also if you need to ignore rule for a few lines of the code then you can use the phpcs:disable, but don’t forget to enable this rule after:

//phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
$my_query = $wpdb->get_results(
	$wpdb->prepare(
		'SELECT name FROM my_table WHERE id=%d',
		$id
	)
);
//phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery

The own coding standard based on WPCS

In my opinion for the middle and more size projects need to create their own codings standard. It’s very easy, just create the phpcs.xml file:

<?xml version="1.0"?>
<ruleset name="AwesomeCS">
	<description>Custom coding standards.</description>
	<rule ref="WordPress"/>
</ruleset>

We create the AwesomeCS coding standard based on the WordPress coding standards.

Arguments

You can add arguments from CLI for your config. For example, argument extensions that can help you work only with the PHP files:

<ruleset name="AwesomeCS">
	<!-- ... -->	
	<arg value="ps"/>
	<arg name="colors"/>
	<arg name="parallel" value="100"/>
	<arg name="extensions" value="php"/>
	<arg name="cache" value=".phpcs.cache"/>
	<!-- ... -->
</ruleset>
  • The ps can show results of check real-time;
  • The colors is just adds the colored output;
  • The parallel checks your files in separate processes. Unfortunately, but this feature based on the PCNTL library and doesn’t works on Non-Unix systems (Windows). But can add the super boost for your speed in the GH actions;
  • The extensions describes the extensions for the checking;
  • The cache is just super boost for the double-checking

Exclude files and directories

Add the list of pattern where phpcs doesn’t check.

<ruleset name="AwesomeCS">
	<!-- ... -->
	<exclude-pattern>\.github/*</exclude-pattern>
	<exclude-pattern>vendor/*</exclude-pattern>
	<exclude-pattern>node_modues/*</exclude-pattern>
	<exclude-pattern>\.idea/*</exclude-pattern>
	<exclude-pattern>assets/*</exclude-pattern>
	<!-- ... -->
</ruleset>

The short array syntax

Frankly the short array syntax it’s uncomfortable and legacy, but important for WordPress coding standard. Let’s update it:

<ruleset name="AwesomeCS">
	<!-- ... -->
	<!-- Allow short array syntax -->
	<rule ref="Generic.Arrays.DisallowShortArraySyntax.Found">
		<severity>0</severity>
	</rule>
	<rule ref="Generic.Arrays.DisallowLongArraySyntax.Found"/>
	<!-- ... -->
</ruleset>

This is a just example of how to add custom rules in your CS.

The PSR-4 naming

I prefer using the composer autoload, so let’s update CS for support PSR-4 naming:

<ruleset name="AwesomeCS">
	<!-- ... -->
	<rule ref="WordPress">
		<!-- PSR4 -->
		<exclude name="WordPress.Files.FileName.InvalidClassFileName"/>
		<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase"/>
	</rule>
	<!-- ... -->
</ruleset>

Cyclomatic Complexity

Cyclomatic complexity is a software metric used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program’s source code.

Wikipedia

This metric will help control code complications and write simpler functions and methods.

<ruleset name="AwesomeCS">
	<!-- ... -->
	<rule ref="Generic.Metrics.CyclomaticComplexity">
		<properties>
			<property name="complexity" value="4"/>
			<property name="absoluteComplexity" value="5"/>
		</properties>
	</rule>
	<!-- ... -->
</ruleset>
  • If the cyclomatic complexity is higher than 4, you will see a warning
  • If the cyclomatic complexity is higher than 5, you will see the error

Nesting Level

<ruleset name="AwesomeCS">
	<!-- ... -->
	<rule ref="Generic.Metrics.NestingLevel">
		<properties>
			<property name="absoluteNestingLevel" value="1"/>
		</properties>
	</rule>
	<!-- ... -->
</ruleset>

If the nesting level is higher than 1, you will see an error.

As example this code will cause an error on CS:

function awesome_function( $items ) {
	if ( is_array( $items ) {
		foreach( $items as $item ) {
			// ...
		}
	}
}

This code needs to be refactored and used early exit from the method/function:

function awesome_function( $items ) {
	if ( ! is_array( $items ) {
		return false;
	}
	foreach( $items as $item ) {
		// ...
	}
}

PHPCompatibility

Just awesome coding standard PHPCompatibility which you can add the minimal support PHP version and phpcs will detect in your code any problem for it. It’s really very well library for public plugins when you need to support the form PHP5.6 to PHP7.4 version. Just run your test in php7.4 and this library can help you find any problem with PHP compatibility in 5.6

Let’s install this library and update config:

composer require phpcompatibility/php-compatibility --dev
<ruleset name="AwesomeCS">
	<!-- ... -->
	<config name="testVersion" value="5.6-"/>
	<rule ref="PHPCompatibility"/>
	<!-- ... -->
</ruleset>

Thanks to this, you can check the compatibility from PHP5.6 to the version on which you are checking the files.

Add your own config to PHPSStorm

File -> Settings -> Editor -> Inspection -> Quality Tools -> PHP_CodeSniffer

In the list of Coding standard select Custom and specify the path to our phpcs.xml

Full config

<?xml version="1.0"?>
<ruleset name="CS">
	<description>Custom coding standards.</description>
	<config name="testVersion" value="5.6-"/>
	<exclude-pattern>\.codeception/*</exclude-pattern>
	<exclude-pattern>\.github/*</exclude-pattern>
	<exclude-pattern>vendor/*</exclude-pattern>
	<exclude-pattern>node_modues/*</exclude-pattern>
	<exclude-pattern>\.idea/*</exclude-pattern>
	<exclude-pattern>assets/*</exclude-pattern>

	<arg value="ps"/>
	<arg name="colors"/>
	<arg name="parallel" value="100"/>
	<arg name="extensions" value="php"/>
	<arg name="cache" value=".phpcs.cache"/>

	<rule ref="WordPress">
		<!-- PSR4 -->
		<exclude name="WordPress.Files.FileName.InvalidClassFileName"/>
		<exclude name="WordPress.Files.FileName.NotHyphenatedLowercase"/>
	</rule>

	<rule ref="PHPCompatibility"/>

	<rule ref="Generic.Metrics.CyclomaticComplexity">
		<properties>
			<property name="complexity" value="3"/>
			<property name="absoluteComplexity" value="5"/>
		</properties>
	</rule>

	<rule ref="Generic.Metrics.NestingLevel">
		<properties>
			<property name="absoluteNestingLevel" value="3"/>
		</properties>
	</rule>

	<!-- Allow short array syntax -->
	<rule ref="Generic.Arrays.DisallowShortArraySyntax.Found">
		<severity>0</severity>
	</rule>
	<rule ref="Generic.Arrays.DisallowLongArraySyntax.Found"/>
</ruleset>

Composer scripts

Add the scripts to run your CS using the composer scripts. Just add to the composer.json next code:

{
...
  "scripts": {
    "cs": "phpcs --standard=.phpcs.xml .",
    "cbf": "phpcbf --standard=.phpcs.xml .",
    ...
  }
...
}

And now you can just run your coding standards and code beautifier and fixer:

composer cs
composer cbf

CS in the GitHub Actions

Create the file .github/workflows/php.yml in your project:

name: My GH Actions

on: push

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Install dependencies
      run: composer install --prefer-dist --no-progress --no-suggest

    - name: Run CS
      run: vendor/bin/phpcs --standard=phpcs.xml .

After push action, your code will be checked on coding standards and you can see results on the GitHub.

If after this detailed article you don’t implement CS verification in your project, then I will come to you in a dream and kick your ass

Leave a Reply

Your email address will not be published. Required fields are marked *