Skip to main content
Version: v1

PHPCS - PHP Code Sniffer

The PHP_CodeSniffer project describes the tool as follows:

PHP_CodeSniffer is a set of two PHP scripts; the main phpcs script that tokenizes PHP, JavaScript and CSS files to detect violations of a defined coding standard, and a second phpcbf script to automatically correct coding standard violations. PHP_CodeSniffer is an essential development tool that ensures your code remains clean and consistent.

PHPCS reports where your PHP breaks the Drupal coding standards. Fixing those violations keeps custom modules, themes and scripts on the same conventions, so code review can skip the formatting nitpicks. Vortex comes with a pre-configured PHPCS ruleset for Drupal projects. The ruleset adds a strict types check and a compatibility check for your PHP version. The bundled phpcbf command fixes the violations that have an automatic fix.

This page is for developers who write PHP in a Vortex project. It shows how to check and fix your code, what the shipped ruleset enforces and how to ignore a rule.

Usage​

Check for violations​

The Ahoy command runs PHPCS, then PHPStan and Rector. The Docker Compose command runs PHPCS alone. To check the code, run 1 of the following commands:

ahoy lint-be

Confirm that the check passed: PHPCS prints no FILE: report, and echo $? prints 0 right after the command.

Fix violations​

The PHPCS report marks each violation that PHPCBF can fix with [x]. To fix the marked violations, run 1 of the following commands:

# Fix all back-end lint issues (Rector, then PHPCBF).
ahoy lint-be-fix

Configuration​

See the PHP_CodeSniffer configuration reference.

All global configuration lives in the phpcs.xml file.

By default, PHPCS checks against the following standards and sniffs:

  • Drupal - the Drupal coding standards
  • DrupalPractice - Drupal best practices
  • Generic.PHP.RequireStrictTypes - a declare(strict_types=1); statement in every file
  • PHPCompatibility - compatibility with the PHP version in testVersion
  • DrevOps - the DrevOps standard, which requires the following:
    • Snake_case names for local variables and parameters
    • PHPUnit data providers that start with dataProvider, match the name of their test and come after it
  • SlevomatCodingStandard.TypeHints.DNFTypeHintFormat - no spaces around | and & in union and intersection types, set through its withSpacesAroundOperators property

The ruleset also adds 3 whitespace sniffs from the standards that ship with PHPCS and reports them as warnings. They flag a blank line after a function's opening brace and a blank line before or after a control structure's closing brace. Warnings fail the check too, because PHPCS exits with a non-zero code when it reports any.

The ruleset allows long array lines in test files. It also exempts the Behat contexts from the project class name prefix.

The ruleset sets the following command-line arguments for every run:

  • colors - colored output
  • s - the sniff code after each message
  • p - a progress indicator
  • parallel set to 10 - 10 parallel processes, which you can change to match your CPU cores

PHPCS checks the following paths, which the <file> entries in phpcs.xml list:

  • web/modules/custom
  • web/themes/custom
  • web/sites/default/settings.php
  • web/sites/default/includes
  • tests
  • scripts

Within them, PHPCS checks files with the inc, info, install, module, php, profile, test and theme extensions. It skips minified files and the build, fonts, images and node_modules directories of custom themes.

To add or remove targets, add or remove the <file> entries in phpcs.xml:

<file>path/to/dir_or_file</file>

The PHPCompatibility checks run against the testVersion value in phpcs.xml, set to 8.4. The composer.json key config.platform.php pins PHP 8.4.27, a patch release of the same version. PHPCS doesn't read that key, so update both values when you move to a new PHP version. The testVersion line looks like this:

<config name="testVersion" value="8.4"/>

Ignore violations​

To ignore a rule across the project, configure it in the phpcs.xml file. The following example turns a rule off for the files that match its patterns:

<!-- Comment about why this rule is excluded. -->
<rule ref="DrupalPractice.General.ClassName.ClassPrefix">
<exclude-pattern>*\/dir\/another\/*\.php</exclude-pattern>
<exclude-pattern>*\/dir\/another\/*\.inc</exclude-pattern>
</rule>

To ignore all PHPCS rules in a file, add this line to the file header:

// phpcs:ignoreFile

To ignore a specific rule in a file, add this line to the file header:

// phpcs:disable <rule_name>

Replace <rule_name> with the sniff code that the report prints in parentheses after the message, such as Drupal.Commenting.FunctionComment.Missing.

To ignore a rule for a block of code, put it between a disable and an enable comment:

// phpcs:disable <rule_name>
$a = 1;
// phpcs:enable <rule_name>

To ignore the next line only, add this comment on the line before it:

// phpcs:ignore
$a = 1;

Continuous integration​

PHPCS runs in the lint job of the continuous integration pipeline and fails the build on violations.

Ignore failures​

To let the build pass anyway, set the VORTEX_CI_PHPCS_IGNORE_FAILURE CI variable to 1. PHPCS still runs and prints every violation in the job log, so you can see what you're letting through.

➡️ See Continuous integration > Ignore tool failures