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 holds your PHP to the Drupal coding standards, so every custom module, theme, and script follows the same conventions and code review can skip the formatting nitpicks. Vortex comes with a pre-configured PHPCS ruleset for Drupal projects. It also requires strict types and checks compatibility with your PHP version, and 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​

ahoy lint-be runs PHPCS first, then PHPStan and Rector, while 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 $?, run straight after the command, prints 0.

Fix violations​

The PHPCS report marks each violation that PHPCBF can fix with [x]. To fix them, 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 - snake_case names for local variables and parameters, and 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

On top of these, the ruleset 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 also allows long array lines in test files and 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 files checked at the same time; adjust it to the number of CPU cores available

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, and 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 PHP 8.4, the testVersion value in phpcs.xml, which matches the composer.json key config.platform.php (8.4.27). PHPCS doesn't read that key, so update both when you move to a new PHP version:

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

Ignoring​

To ignore a rule across the project, configure it in the phpcs.xml file. This example turns a rule off for the files that match the 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.

Ignoring 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 exactly what you're letting through.

➡️ See Continuous integration > Ignore tool failures