PHPCS: PHP CodeSniffer

Contents
Install
Install on Linux
Install on macOS
Install on Windows
Run with Docker
First run
Spaces around operators
Lowercase true and false
Trailing whitespace
Use block spacing
CamelCase method names
Fix automatically

Install

PHPCS (PHP CodeSniffer) checks your code against a coding standard such as PSR-12 and reports every violation with file, line and a fixable [x] mark. Its twin PHPCBF fixes the safe ones for you. Pick one installation method below — they all give you the same two binaries, phpcs and phpcbf.

Install on Linux

Brief command chain to install PHPCS on Linux (Ubuntu/Debian):

sudo apt install -y composer php -v

Notice the PHP version.

In this example it is 8.1, so we will install the PHP CodeSniffer for PHP 8.1.

sudo apt install php8.1-xml composer require --dev squizlabs/php_codesniffer:^3.13 vendor/bin/phpcs --version

Usage example: check a file for PSR-2 violations and fix them automatically:

vendor/bin/phpcbf --standard=phpcs.xml --sniffs=PSR2.Methods.FunctionCallSignature -- src/ru/qa/.php/Page.php

PHPCBF RESULT SUMMARY --------------------------------------------------------------------------------- FILE FIXED REMAINING --------------------------------------------------------------------------------- /home/andrei/github/aredel/container/src/ru/qa/.php/Page.php 81 0 --------------------------------------------------------------------------------- A TOTAL OF 81 ERRORS WERE FIXED IN 1 FILE --------------------------------------------------------------------------------- Time: 582ms; Memory: 12MB

Detailed path that I followed to install phpcs on Linux:

You may need to install composer first, then require the package.

sudo apt install composer

Skip output

[sudo] password for andrei: Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: libfwupd2 libfwupdplugin5 libgcab-1.0-0 libllvm13 libsmbios-c2 libwpe-1.0-1 libwpebackend-fdo-1.0-1 nvidia-firmware-535-server-535.230.02 Use 'sudo apt autoremove' to remove them. The following additional packages will be installed: jsonlint php-composer-ca-bundle php-composer-metadata-minifier php-composer-pcre php-composer-semver php-composer-spdx-licenses php-composer-xdebug-handler php-intl php-json-schema php-mbstring php-psr-container php-psr-log php-react-promise php-symfony-console php-symfony-deprecation-contracts php-symfony-filesystem php-symfony-finder php-symfony-polyfill-php80 php-symfony-process php-symfony-service-contracts php-symfony-string php8.1-intl php8.1-mbstring Suggested packages: fossil mercurial subversion php-zip php-symfony-event-dispatcher php-symfony-lock php-symfony-service-implementation The following NEW packages will be installed: composer jsonlint php-composer-ca-bundle php-composer-metadata-minifier php-composer-pcre php-composer-semver php-composer-spdx-licenses php-composer-xdebug-handler php-intl php-json-schema php-mbstring php-psr-container php-psr-log php-react-promise php-symfony-console php-symfony-deprecation-contracts php-symfony-filesystem php-symfony-finder php-symfony-polyfill-php80 php-symfony-process php-symfony-service-contracts php-symfony-string php8.1-intl php8.1-mbstring 0 upgraded, 24 newly installed, 0 to remove and 7 not upgraded. Need to get 1 416 kB of archives. After this operation, 6 299 kB of additional disk space will be used. Do you want to continue? [Y/n] Y Get:1 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-composer-ca-bundle all 1.3.1-1 [10,4 kB] Get:2 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-composer-metadata-minifier all 1.0.0-2 [3 594 B] Get:3 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-composer-semver all 3.2.9-1 [18,2 kB] Get:4 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-composer-spdx-licenses all 1.5.6-1 [13,2 kB] Get:5 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-psr-log all 3.0.0-1 [6 862 B] Get:6 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-composer-pcre all 1.0.1-1 [7 810 B] Get:7 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-composer-xdebug-handler all 2.0.4-1build1 [16,6 kB] Get:8 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-json-schema all 5.2.11-1 [33,9 kB] Get:9 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 jsonlint all 1.8.3-2 [12,1 kB] Get:10 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-deprecation-contracts all 2.4.0-1ubuntu2 [4 700 B] Get:11 http://fi.archive.ubuntu.com/ubuntu jammy-updates/main amd64 php8.1-mbstring amd64 8.1.2-1ubuntu2.26 [483 kB] Get:12 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-mbstring all 2:8.1+92ubuntu1 [1 844 B] Get:13 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-polyfill-php80 all 1.24.0-1ubuntu2 [6 642 B] Get:14 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-psr-container all 2.0.2-1 [3 878 B] Get:15 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-service-contracts all 2.4.0-1ubuntu2 [8 136 B] Get:16 http://fi.archive.ubuntu.com/ubuntu jammy-updates/universe amd64 php8.1-intl amd64 8.1.2-1ubuntu2.26 [142 kB] Get:17 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-intl all 2:8.1+92ubuntu1 [1 840 B] Get:18 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-string all 5.4.4+dfsg-1ubuntu8 [36,8 kB] Get:19 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-console all 5.4.4+dfsg-1ubuntu8 [84,1 kB] Get:20 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-filesystem all 5.4.4+dfsg-1ubuntu8 [23,9 kB] Get:21 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-finder all 5.4.4+dfsg-1ubuntu8 [24,9 kB] Get:22 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-symfony-process all 5.4.4+dfsg-1ubuntu8 [28,6 kB] Get:23 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 php-react-promise all 2.7.0-2 [16,4 kB] Get:24 http://fi.archive.ubuntu.com/ubuntu jammy/universe amd64 composer all 2.2.6-2ubuntu4 [425 kB] Fetched 1 416 kB in 1s (1 581 kB/s) Selecting previously unselected package php-composer-ca-bundle. (Reading database ... 256805 files and directories currently installed.) Preparing to unpack .../00-php-composer-ca-bundle_1.3.1-1_all.deb ... Unpacking php-composer-ca-bundle (1.3.1-1) ... Selecting previously unselected package php-composer-metadata-minifier. Preparing to unpack .../01-php-composer-metadata-minifier_1.0.0-2_all.deb ... Unpacking php-composer-metadata-minifier (1.0.0-2) ... Selecting previously unselected package php-composer-semver. Preparing to unpack .../02-php-composer-semver_3.2.9-1_all.deb ... Unpacking php-composer-semver (3.2.9-1) ... Selecting previously unselected package php-composer-spdx-licenses. Preparing to unpack .../03-php-composer-spdx-licenses_1.5.6-1_all.deb ... Unpacking php-composer-spdx-licenses (1.5.6-1) ... Selecting previously unselected package php-psr-log. Preparing to unpack .../04-php-psr-log_3.0.0-1_all.deb ... Unpacking php-psr-log (3.0.0-1) ... Selecting previously unselected package php-composer-pcre. Preparing to unpack .../05-php-composer-pcre_1.0.1-1_all.deb ... Unpacking php-composer-pcre (1.0.1-1) ... Selecting previously unselected package php-composer-xdebug-handler. Preparing to unpack .../06-php-composer-xdebug-handler_2.0.4-1build1_all.deb ... Unpacking php-composer-xdebug-handler (2.0.4-1build1) ... Selecting previously unselected package php-json-schema. Preparing to unpack .../07-php-json-schema_5.2.11-1_all.deb ... Unpacking php-json-schema (5.2.11-1) ... Selecting previously unselected package jsonlint. Preparing to unpack .../08-jsonlint_1.8.3-2_all.deb ... Unpacking jsonlint (1.8.3-2) ... Selecting previously unselected package php-symfony-deprecation-contracts. Preparing to unpack .../09-php-symfony-deprecation-contracts_2.4.0-1ubuntu2_all.deb ... Unpacking php-symfony-deprecation-contracts (2.4.0-1ubuntu2) ... Selecting previously unselected package php8.1-mbstring. Preparing to unpack .../10-php8.1-mbstring_8.1.2-1ubuntu2.26_amd64.deb ... Unpacking php8.1-mbstring (8.1.2-1ubuntu2.26) ... Selecting previously unselected package php-mbstring. Preparing to unpack .../11-php-mbstring_2%3a8.1+92ubuntu1_all.deb ... Unpacking php-mbstring (2:8.1+92ubuntu1) ... Selecting previously unselected package php-symfony-polyfill-php80. Preparing to unpack .../12-php-symfony-polyfill-php80_1.24.0-1ubuntu2_all.deb ... Unpacking php-symfony-polyfill-php80 (1.24.0-1ubuntu2) ... Selecting previously unselected package php-psr-container. Preparing to unpack .../13-php-psr-container_2.0.2-1_all.deb ... Unpacking php-psr-container (2.0.2-1) ... Selecting previously unselected package php-symfony-service-contracts. Preparing to unpack .../14-php-symfony-service-contracts_2.4.0-1ubuntu2_all.deb ... Unpacking php-symfony-service-contracts (2.4.0-1ubuntu2) ... Selecting previously unselected package php8.1-intl. Preparing to unpack .../15-php8.1-intl_8.1.2-1ubuntu2.26_amd64.deb ... Unpacking php8.1-intl (8.1.2-1ubuntu2.26) ... Selecting previously unselected package php-intl. Preparing to unpack .../16-php-intl_2%3a8.1+92ubuntu1_all.deb ... Unpacking php-intl (2:8.1+92ubuntu1) ... Selecting previously unselected package php-symfony-string. Preparing to unpack .../17-php-symfony-string_5.4.4+dfsg-1ubuntu8_all.deb ... Unpacking php-symfony-string (5.4.4+dfsg-1ubuntu8) ... Selecting previously unselected package php-symfony-console. Preparing to unpack .../18-php-symfony-console_5.4.4+dfsg-1ubuntu8_all.deb ... Unpacking php-symfony-console (5.4.4+dfsg-1ubuntu8) ... Selecting previously unselected package php-symfony-filesystem. Preparing to unpack .../19-php-symfony-filesystem_5.4.4+dfsg-1ubuntu8_all.deb ... Unpacking php-symfony-filesystem (5.4.4+dfsg-1ubuntu8) ... Selecting previously unselected package php-symfony-finder. Preparing to unpack .../20-php-symfony-finder_5.4.4+dfsg-1ubuntu8_all.deb ... Unpacking php-symfony-finder (5.4.4+dfsg-1ubuntu8) ... Selecting previously unselected package php-symfony-process. Preparing to unpack .../21-php-symfony-process_5.4.4+dfsg-1ubuntu8_all.deb ... Unpacking php-symfony-process (5.4.4+dfsg-1ubuntu8) ... Selecting previously unselected package php-react-promise. Preparing to unpack .../22-php-react-promise_2.7.0-2_all.deb ... Unpacking php-react-promise (2.7.0-2) ... Selecting previously unselected package composer. Preparing to unpack .../23-composer_2.2.6-2ubuntu4_all.deb ... Unpacking composer (2.2.6-2ubuntu4) ... Setting up php8.1-mbstring (8.1.2-1ubuntu2.26) ... Creating config file /etc/php/8.1/mods-available/mbstring.ini with new version Setting up jsonlint (1.8.3-2) ... Setting up php-psr-container (2.0.2-1) ... Setting up php-composer-pcre (1.0.1-1) ... Setting up php-symfony-service-contracts (2.4.0-1ubuntu2) ... Setting up php-mbstring (2:8.1+92ubuntu1) ... Setting up php-composer-ca-bundle (1.3.1-1) ... Setting up php-react-promise (2.7.0-2) ... Setting up php-psr-log (3.0.0-1) ... Setting up php-symfony-polyfill-php80 (1.24.0-1ubuntu2) ... Setting up php-composer-metadata-minifier (1.0.0-2) ... Setting up php-composer-semver (3.2.9-1) ... Setting up php-json-schema (5.2.11-1) ... Setting up php-composer-spdx-licenses (1.5.6-1) ... Setting up php8.1-intl (8.1.2-1ubuntu2.26) ... Creating config file /etc/php/8.1/mods-available/intl.ini with new version Setting up php-symfony-deprecation-contracts (2.4.0-1ubuntu2) ... Setting up php-symfony-finder (5.4.4+dfsg-1ubuntu8) ... Setting up php-composer-xdebug-handler (2.0.4-1build1) ... Setting up php-intl (2:8.1+92ubuntu1) ... Setting up php-symfony-process (5.4.4+dfsg-1ubuntu8) ... Setting up php-symfony-filesystem (5.4.4+dfsg-1ubuntu8) ... Setting up php-symfony-string (5.4.4+dfsg-1ubuntu8) ... Setting up php-symfony-console (5.4.4+dfsg-1ubuntu8) ... Setting up composer (2.2.6-2ubuntu4) ... Processing triggers for man-db (2.10.2-1) ... Processing triggers for php8.1-cli (8.1.2-1ubuntu2.26) ...

With Composer, per project (recommended — pins the version for the team):

composer require --dev phpcsstandards/php_codesniffer

Using version ^2.2 for phpcsstandards/php_codesniffer ./composer.json has been created Running composer update phpcsstandards/php_codesniffer Loading composer repositories with package information Updating dependencies Lock file operations: 1 install, 0 updates, 0 removals - Locking phpcsstandards/php_codesniffer (2.2.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Downloading phpcsstandards/php_codesniffer (2.2.0) - Installing phpcsstandards/php_codesniffer (2.2.0): Extracting archive Package phpcsstandards/php_codesniffer is abandoned, you should avoid using it. Use squizlabs/php_codesniffer instead. Generating autoload files

composer remove phpcsstandards/php_codesniffer

phpcsstandards/php_codesniffer could not be found in require but it is present in require-dev Do you want to remove it from require-dev [yes]? yes ./composer.json has been updated Running composer update phpcsstandards/php_codesniffer Loading composer repositories with package information Updating dependencies Lock file operations: 0 installs, 0 updates, 1 removal - Removing phpcsstandards/php_codesniffer (2.2.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 0 installs, 0 updates, 1 removal - Removing phpcsstandards/php_codesniffer (2.2.0) Generating autoload files

composer require --dev squizlabs/php_codesniffer

Using version ^2.2 for squizlabs/php_codesniffer ./composer.json has been updated Running composer update squizlabs/php_codesniffer Loading composer repositories with package informati Updating dependencies Lock file operations: 1 install, 0 updates, 0 remova - Locking squizlabs/php_codesniffer (2.2.0) Writing lock file Installing dependencies from lock file (including re Package operations: 1 install, 0 updates, 0 removals - Downloading squizlabs/php_codesniffer (2.2.0) - Installing squizlabs/php_codesniffer (2.2.0): Ex Generating autoload files 1 package you are using is looking for funding. Use the `composer fund` command to find out more!

vendor/bin/phpcs --version

PHP Fatal error: Array and string offset access syntax with curly braces is no longer supported in /home/andrei/github/aredel/container/vendor/squizlabs/php_codesniffer/CodeSniffer/CLI.php on line 418

composer remove squizlabs/php_codesniffer

squizlabs/php_codesniffer could not be found in require but it is present in require-dev Do you want to remove it from require-dev [yes]? yes ./composer.json has been updated Running composer update squizlabs/php_codesniffer Loading composer repositories with package information Updating dependencies Lock file operations: 0 installs, 0 updates, 1 removal - Removing squizlabs/php_codesniffer (2.2.0) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 0 installs, 0 updates, 1 removal - Removing squizlabs/php_codesniffer (2.2.0) Generating autoload files

composer require --dev squizlabs/php_codesniffer:^3.13

In InitCommand.php line 904: Package squizlabs/php_codesniffer at version ^3.13 has requirements incompatible with your PHP version, PHP extensions and Composer vers ion: - squizlabs/php_codesniffer 3.13.6 requires ext-simplexml * but it is not present. - squizlabs/php_codesniffer 3.13.6 requires ext-xmlwriter * but it is not present. require [--dev] [--dry-run] [--prefer-source] [--prefer-dist] [--prefer-install PREFER-INSTALL] [--fixed] [--no-suggest] [--no-progress] [--no-update] [--no-install] [--update-no-dev] [-w|--update-with-dependencies] [-W|--update-with-all-dependencies] [--with-dependencies] [--with-all-dependencies] [--ignore-platform-req IGNORE-PLATFORM-REQ] [--ignore-platform-reqs] [--prefer-stable] [--prefer-lowest] [--sort-packages] [-o|--optimize-autoloader] [-a|--classmap-authoritative] [--apcu-autoloader] [--apcu-autoloader-prefix APCU-AUTOLOADER-PREFIX] [--] [...]

php -v

PHP 8.1.2-1ubuntu2.26 (cli) (built: Sep 2 2026 12:42:10) (NTS) Copyright (c) The PHP Group Zend Engine v4.1.2, Copyright (c) Zend Technologies with Zend OPcache v8.1.2-1ubuntu2.26, Copyright (c), by Zend Technologies

sudo apt install php8.2-xml

[sudo] password for andrei: Reading package lists... Done Building dependency tree... Done Reading state information... Done E: Unable to locate package php8.2-xml E: Couldn't find any package by glob 'php8.2-xml'

apt list --installed 2>/dev/null | grep -i php | head

php-cli/jammy,jammy,now 2:8.1+92ubuntu1 all [installed] php-common/jammy,jammy,now 2:92ubuntu1 all [installed,automatic] php-composer-ca-bundle/jammy,jammy,now 1.3.1-1 all [installed,automatic] php-composer-metadata-minifier/jammy,jammy,now 1.0.0-2 all [installed,automatic] php-composer-pcre/jammy,jammy,now 1.0.1-1 all [installed,automatic] php-composer-semver/jammy,jammy,now 3.2.9-1 all [installed,automatic] php-composer-spdx-licenses/jammy,jammy,now 1.5.6-1 all [installed,automatic] php-composer-xdebug-handler/jammy,jammy,now 2.0.4-1build1 all [installed,automatic] php-intl/jammy,jammy,now 2:8.1+92ubuntu1 all [installed,automatic] php-json-schema/jammy,jammy,now 5.2.11-1 all [installed,automatic]

ls /etc/php/

8.1

Now we need either to upgrade PHP to 8.2 or install the missing extensions for 8.1. The latter is easier:

sudo apt install php8.1-xml

Reading package lists... Done Building dependency tree... Done Reading state information... Done The following packages were automatically installed and are no longer required: libfwupd2 libfwupdplugin5 libgcab-1.0-0 libllvm13 libsmbios-c2 libwpe-1.0-1 libwpebackend-fdo-1.0-1 nvidia-firmware-535-server-535.230.02 Use 'sudo apt autoremove' to remove them. The following NEW packages will be installed: php8.1-xml 0 upgraded, 1 newly installed, 0 to remove and 7 not upgraded. Need to get 120 kB of archives. After this operation, 484 kB of additional disk space will be used. Get:1 http://fi.archive.ubuntu.com/ubuntu jammy-updates/main amd64 php8.1-xml amd64 8.1.2-1ubuntu2.26 [120 kB] Fetched 120 kB in 0s (547 kB/s) Selecting previously unselected package php8.1-xml. (Reading database ... 257661 files and directories currently installed.) Preparing to unpack .../php8.1-xml_8.1.2-1ubuntu2.26_amd64.deb ... Unpacking php8.1-xml (8.1.2-1ubuntu2.26) ... Setting up php8.1-xml (8.1.2-1ubuntu2.26) ... Creating config file /etc/php/8.1/mods-available/dom.ini with new version Creating config file /etc/php/8.1/mods-available/simplexml.ini with new version Creating config file /etc/php/8.1/mods-available/xml.ini with new version Creating config file /etc/php/8.1/mods-available/xmlreader.ini with new version Creating config file /etc/php/8.1/mods-available/xmlwriter.ini with new version Creating config file /etc/php/8.1/mods-available/xsl.ini with new version Processing triggers for php8.1-cli (8.1.2-1ubuntu2.26) ...

php -m | grep -i -e simplexml -e xmlwriter

SimpleXML xmlwriter

composer require --dev squizlabs/php_codesniffer:^3.13

./composer.json has been updated Running composer update squizlabs/php_codesniffer Loading composer repositories with package information Updating dependencies Lock file operations: 1 install, 0 updates, 0 removals - Locking squizlabs/php_codesniffer (3.13.6) Writing lock file Installing dependencies from lock file (including require-dev) Package operations: 1 install, 0 updates, 0 removals - Downloading squizlabs/php_codesniffer (3.13.6) - Installing squizlabs/php_codesniffer (3.13.6): Extracting archive Generating autoload files 1 package you are using is looking for funding. Use the `composer fund` command to find out more!

vendor/bin/phpcs --version

PHP_CodeSniffer version 3.13.6 (stable) by Squiz and PHPCSStandards

Now we can run the code fixer on the file with the control signature sniff:

vendor/bin/phpcbf --standard=phpcs.xml --sniffs=Squiz.ControlStructures.ControlSignature -- src/ru/qa/.php/Page.php

PHPCBF RESULT SUMMARY --------------------------------------------------------------------------------- FILE FIXED REMAINING --------------------------------------------------------------------------------- /home/andrei/github/aredel/container/src/ru/qa/.php/Page.php 44 0 --------------------------------------------------------------------------------- A TOTAL OF 44 ERRORS WERE FIXED IN 1 FILE --------------------------------------------------------------------------------- Time: 265ms; Memory: 12MB

And then on the scope indent sniff:

vendor/bin/phpcbf --standard=phpcs.xml --sniffs=Generic.WhiteSpace.ScopeIndent -- src/ru/qa/.php/Page.php

PHPCBF RESULT SUMMARY --------------------------------------------------------------------------------- FILE FIXED REMAINING --------------------------------------------------------------------------------- /home/andrei/github/aredel/container/src/ru/qa/.php/Page.php 9 0 --------------------------------------------------------------------------------- A TOTAL OF 9 ERRORS WERE FIXED IN 1 FILE --------------------------------------------------------------------------------- Time: 246ms; Memory: 12MB

And finally on the closing brace sniffs:

vendor/bin/phpcbf --standard=phpcs.xml --sniffs=Squiz.WhiteSpace.ScopeClosingBrace,PSR2.Methods.FunctionClosingBrace -- src/ru/qa/.php/Page.php

No violations were found Time: 117ms; Memory: 10MB

Install on Linux (alternative)

Or once per user, available in every shell:

composer global require phpcsstandards/php_codesniffer export PATH="$HOME/.composer/vendor/bin:$PATH"

Without Composer, download the PHAR from the GitHub releases page of PHPCSStandards/PHP_CodeSniffer and run it with your PHP interpreter:

php phpcs.phar --version php phpcbf.phar --version

Install on macOS

Same Composer commands as on Linux. PHP itself comes either from the system, from Homebrew (brew install php) or from a Docker image — PHPCS only needs any PHP 7.2+ binary to run:

php -v composer require --dev phpcsstandards/php_codesniffer vendor/bin/phpcs --version

Install on Windows

Install PHP and Composer for Windows, then require the package. Composer creates vendor\bin\phpcs.bat wrappers, so both tools run from cmd or PowerShell:

composer require --dev phpcsstandards/php_codesniffer vendor\bin\phpcs --version vendor\bin\phpcs --standard=PSR12 file.php

The PHAR alternative works too, prefixing every call with php:

php phpcs.phar --standard=PSR12 file.php

Run with Docker

No host PHP at all: mount the project into an official PHP image together with the downloaded PHAR files:

docker run --rm -v "$PWD:/app" -w /app \ -v "$HOME/.cache/aredel-tools:/tools:ro" php:8.2-cli \ php /tools/phpcs.phar --standard=PSR12 --report=full app/

List every installed standard, and show the sniff code behind each message with -s:

phpcs -i phpcs -s --standard=PSR12 file.php

First run

Take a file with several typical style problems:

<?php use App\Util; use App\Helper; $greeting="Hello"; $name="world"; echo $greeting.$name; $enabled = TRUE; class Greeter { public function say_hello() { return "hi"; } }

phpcs --standard=PSR12 --report=full bad.php

FILE: bad.php
FOUND 12 ERRORS AND 1 WARNING AFFECTING 9 LINES
3 | ERROR | [x] Header blocks must not contain blank lines
7 | ERROR | [x] Expected at least 1 space before "="; 0 found
9 | ERROR | [x] Expected at least 1 space before "."; 0 found
9 | ERROR | [x] Whitespace found at end of line
10 | ERROR | [x] TRUE, FALSE and NULL must be lowercase
14 | ERROR | [ ] Method name "Greeter::say_hello" is not in camel caps format
18 | ERROR | [x] Expected 1 newline at end of file; 0 found

The rest of this article walks through each error type: what it means, how to fix it by hand, and what remains afterwards.

Spaces around operators

PSR-12 wants exactly one space on each side of = and the concatenation operator .. Before:

$greeting="Hello"; echo $greeting.$name;

After — the complaint disappears:

$greeting = "Hello"; echo $greeting . $name;

Lowercase true and false

TRUE, FALSE and NULL must be lowercase. Before:

$enabled = TRUE;

After:

$enabled = true;

Trailing whitespace

Spaces or tabs after the last visible character, and a missing newline at the very end of the file, are both errors. They are invisible in most editors — turn on render whitespace or let phpcbf strip them:

echo $greeting . $name;···

9 | ERROR | [x] Whitespace found at end of line
18 | ERROR | [x] Expected 1 newline at end of file; 0 found

Use block spacing

The header block — <?php, then use statements — must not contain blank lines. Before:

use App\Util; use App\Helper;

After:

use App\Util; use App\Helper;

CamelCase method names

Method names must be camelCase. Unlike every error above, this one carries no [x] mark — PHPCS will never fix it for you, because renaming a method means updating every caller:

public function say_hello()

14 | ERROR | [ ] Method name "Greeter::say_hello" is not in camel caps format

Rename by hand, then update each call site:

public function sayHello()

Fix automatically

Run the twin binary on the original file. It fixes all ten [x] violations in place — spacing, lowercase, header block, trailing whitespace, end-of-file newline:

phpcbf --standard=PSR12 bad.php

A TOTAL OF 10 ERRORS WERE FIXED IN 1 FILE

Re-checking shows only the two findings that need a human left: the file mixes a class with top-level code, and the method name from the previous chapter. After putting the code in a namespace and renaming the method, the report is empty:

phpcs --standard=PSR12 good.php

(no output — 0 errors, 0 warnings)

Always re-run phpcs after phpcbf: the fixer reports how much it touched, not what remains. And review the diff — automatic fixes are safe, but they are still changes to your code.

Article author: Andrei Olegovich

Related articles
Development with PHP
PHP linters we use
php -l and lint-php.sh
PHPCS: PHP CodeSniffer
phpcs.xml ruleset file
PHPCBF: fix style automatically
wrap-long-lines.sh
PHPStan and Psalm
Banner image

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.ru
Write to info@urn.su if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: