PHP Code Sniffer - In-depth Tutorial for Developers

Learn how to integrate PHP Code Sniffer into your development workflow and create coding standards tailored to your needs. Discover how it works, from its core functionalities to its integration with Visual Studio Code and don't miss any problems ever again.

tl;drGitHub

If you work with PHP you probably heard about PHP Code Sniffer. And I'm not surprised! There are plenty of articles with basic knowledge about how to set it up, and if you think that's another one, please let me give you something more.

Because, in the latest material on my channel, I'll provide the knowledge that I wish to have when starting my adventure with this tool. The knowledge that is not discussed so often. Of course, you'll find some basics too, but what's more important, you'll get more advanced tips that will help you build solutions that work for you, for your real needs. 

Welcome back, I'm Przemek and in this material, I'll talk about setting up PHP Code Sniffer and performing more advanced configurations to let you build your own rules.


What is PHP Code Sniffer?

PHP Code Sniffer is a command line tool that ensures your PHP code remains clean and consistent with a specific coding standard. It consists of two scripts: phpcs - linter that checks what is wrong with the code, and phpcbf - formatter that tries to fix problems.

A coding standard in PHP Code Sniffer is a collection of sniffs, each identified by the code using the Standard.Category.Name pattern. A single sniff is designed to find one or more rule violations which also have a unique identifier: Standard.Category.Name.Error.

For example, the Generic.Arrays.DisallowLongArraySyntax sniff checks if the code uses a long array syntax like array(). If so, phpcs informs that it's not allowed and that the short syntax [] should be used instead. That's a pretty fast check showing just one fix.

class Hooks
{
    public static function init(): void {
        $foo = array();
    }
}
FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
-----------------------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
-----------------------------------------------------------------------------------------------------------------
7 | ERROR | [x] Short array syntax must be used to define arrays (Generic.Arrays.DisallowLongArraySyntax)
-----------------------------------------------------------------------------------------------------------------

Another example is Squiz.ControlStructures.ForEachLoopDeclaration sniff which ensures a space between each element of a foreach loop and lowercase keyword. Compared to the previous example, this rule might be violated in different ways, so as a result, we get more errors to fix, e.g. Squiz.ControlStructures.ForEachLoopDeclaration.SpaceAfterOpen.

class Hooks
{
    public static function init(): void {
        foreach ( [] AS $bar=>$baz ) {
            echo $baz;
        }
    }
}
FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
----------------------------------------------------------------------------------------------------------------------------------------
FOUND 5 ERRORS AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------------------------------------------
7 | ERROR | [x] Space found after opening bracket of FOREACH loop (Squiz.ControlStructures.ForEachLoopDeclaration.SpaceAfterOpen)
7 | ERROR | [x] Space found before closing bracket of FOREACH loop (Squiz.ControlStructures.ForEachLoopDeclaration.SpaceBeforeClose)
7 | ERROR | [x] Expected 1 space before "=>"; 0 found (Squiz.ControlStructures.ForEachLoopDeclaration.NoSpaceBeforeArrow)
7 | ERROR | [x] Expected 1 space after "=>"; 0 found (Squiz.ControlStructures.ForEachLoopDeclaration.NoSpaceAfterArrow)
7 | ERROR | [x] AS keyword must be lowercase; expected "as" but found "AS" (Squiz.ControlStructures.ForEachLoopDeclaration.AsNotLower)
----------------------------------------------------------------------------------------------------------------------------------------

If we want those rules to be respected across the codebase, we can create a new coding standard to ensure that the codebase meets our needs. Of course, there's no need to build them from scratch. PHP Code Sniffer includes several standards like PSR1, PSR12, PEAR, and a few more within installation, so we can use one of them.

This is simply the way how the standards are built. Just by choosing specific sniffs and adding them to the ruleset. You can simply check them: Pear, PSR12, Squiz and others.

Image


How to install PHP Code Sniffer?

We can install the tool globally using official instructions or Homebrew, but here, we’ll go with local installation using  composer. Open the terminal, go to the theme or plugin directory, and add PHP Code Sniffer to your codebase with composer require command. Remember to do it with --dev flag to skip the package in the production release!

composer require squizlabs/php_codesniffer --dev

How to use PHP Code Sniffer?

The simplest way to search for the violations in our code is to use the vendor/bin/phpcs script, provide the location to check - the file or directory - and specify the coding rules. The tool will check all the files there and list all the problems with their exact location. We can navigate through them and fix all the problems manually one by one.

vendor/bin/phpcs app/Core/Hooks.php --standard=PSR12

FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
---------------------------------------------------------------------------------------------------------
FOUND 4 ERRORS AND 1 WARNING AFFECTING 4 LINES
---------------------------------------------------------------------------------------------------------
  1 | ERROR   | [x] Header blocks must be separated by a single blank line
  6 | WARNING | [ ] Line exceeds 120 characters; contains 122 characters
  8 | ERROR   | [x] Opening brace should be on a new line
---------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
---------------------------------------------------------------------------------------------------------

I hope that you know I'm joking. I was seriously involved in weird discussions with developers about exceeding a task budget caused by reviewing files and making the violation fixes manually one by one. And it wasn't a single situation so not everyone gets this 😒 The report that we get after using the linter presents two types of potential violations: the ones that can be automatically fixed [x], and the ones that can't [ ].

FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
---------------------------------------------------------------------------------------------------------
FOUND 4 ERRORS AND 1 WARNING AFFECTING 4 LINES
---------------------------------------------------------------------------------------------------------
  1 | ERROR   | [x] Header blocks must be separated by a single blank line
  6 | WARNING | [ ] Line exceeds 120 characters; contains 122 characters
  8 | ERROR   | [x] Opening brace should be on a new line
---------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
---------------------------------------------------------------------------------------------------------
FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
---------------------------------------------------------------------------------------------------------
FOUND 4 ERRORS AND 1 WARNING AFFECTING 4 LINES
---------------------------------------------------------------------------------------------------------
  1 | ERROR   | [x] Header blocks must be separated by a single blank line
  6 | WARNING | [ ] Line exceeds 120 characters; contains 122 characters
  8 | ERROR   | [x] Opening brace should be on a new line
---------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
---------------------------------------------------------------------------------------------------------

The first ones are mostly simple formatting problems that can be fixed only in one way, so the tool can simply handle them for us. The second ones need more attention since they require a well-thought-out decision or manual changes. So let's try to use phpcbf script to format the code for us and reduce the time needed for fixes a million times.

vendor/bin/phpcbf app/Core/Hooks.php --standard=PSR12

PHPCBF RESULT SUMMARY
------------------------------------------------------------------------------------------------------------------------
FILE                                                                                                    FIXED  REMAINING
------------------------------------------------------------------------------------------------------------------------
/Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php     4      1
------------------------------------------------------------------------------------------------------------------------
A TOTAL OF 4 ERRORS WERE FIXED IN 1 FILE
------------------------------------------------------------------------------------------------------------------------

The tool handled all the fixable problems automatically and informed me that there was one problem that needed attention. Once fixed, we can fire phpcs to see that there are no more problems to solve, meaning that the code is compliant with the rules.


How to ignore PHP Code Sniffer errors?

Another important part of the tool usage is ignoring the errors in the code. Sometimes, we NEED to write the code in a specific way, even when it breaks some rules. In Poland we say chodźby skały srały, to ma być tak i ch*j.

We can simply ignore next-line errors with phpcs:ignore comments, code range with the phpcs:disable and phpcs:enable comments, or reduce ignoring just to specific sniffs or standards. Of course, there are many more possibilities so check out them in the doc.

vendor/bin/phpcs app/Core/Hooks.php

FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
----------------------------------------------------------------------------------------------------------------------
FOUND 5 ERRORS AFFECTING 4 LINES
----------------------------------------------------------------------------------------------------------------------
1 | ERROR | [x] Header blocks must be separated by a single blank line (PSR12.Files.FileHeader.SpacingAfterBlock)
5 | ERROR | [x] Opening class brace must be on a line by itself (PSR2.Classes.ClassDeclaration.OpenBraceNotAlone)
5 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
6 | ERROR | [x] Opening brace should be on a new line (Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine)
9 | ERROR | [x] Expected 1 newline at end of file; 0 found (PSR2.Files.EndFileNewline.NoneFound)
----------------------------------------------------------------------------------------------------------------------
namespace FM\Core;

class Hooks
{
    // phpcs:ignore
    public static function init(): void {
        $foo = array();
    }
}
namespace FM\Core;

class Hooks
{
    // phpcs:disable
    public static function init(): void {
        $foo = array();
    }
    // phpcs:enable
}
namespace FM\Core;

class Hooks
{
    // phpcs:ignore Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine
    public static function init(): void {
        $foo = array();
    }
}
vendor/bin/phpcs app/Core/Hooks.php

FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
--------------------------------------------------------------------------------------------------------------------
FOUND 5 ERRORS AFFECTING 3 LINES
--------------------------------------------------------------------------------------------------------------------
 1 | ERROR | [x] Header blocks must be separated by a single blank line (PSR12.Files.FileHeader.SpacingAfterBlock)
 5 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
10 | ERROR | [x] Expected 1 newline at end of file; 0 found (PSR2.Files.EndFileNewline.NoneFound)
10 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
--------------------------------------------------------------------------------------------------------------------

Of course, by saying "We can use it" I don't mean "We can ignore the whole codebase". It requires a delicate balance between adherence to standards and pragmatic coding need. So please, be careful because the project leader might not be happy 😅


How to configure PHP Code Sniffer?

Let's say that, we want to have a more personalized approach to checking the PHP code for potential problems. PHP Code Sniffer allows modifying its default behavior with a wide set of command line arguments so we can use them to define custom workflow. We want to use PSR12 coding standards, check only files located within the app folder, and print color output. We can use the following command.

vendor/bin/phpcs app --standard=PSR12 --colors

We can simplify it and reduce the number of arguments we need to pass in the terminal by defining the configuration file phpcs.xml.dist in the theme or the plugin directory. Tool will search for this file in the current and parent directories - when no standard is specified in the command line - and use the configuration defined there.

<?xml version="1.0"?>

<ruleset name="tentypdev">
  <arg name="colors" />

  <file>app</file>

  <rule ref="PSR12" />
</ruleset>

Now, we can use the vendor/bin/phpcs command without specifying any arguments and everything works as earlier when we used CLI arguments 🎉

vendor/bin/phpcs

The config file might be used also to make even more personalized choices related to the code formatting. Let's say that we don't want to follow the rule applied by the PSR12 standard stating that the function opening brace should be in the new line.

namespace FM\Core;

class Hooks
{
    public static function init(): void {
        $foo = array();
    }
}
vendor/bin/phpcs app/Core/Hooks.php

FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
----------------------------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------------------------
7 | ERROR | [x] Opening brace should be on a new line
----------------------------------------------------------------------------------------------------------------------

To reflect this in the phpcs config, we need to know the unique identifier of the rule that checks this first. We can find it out by adding the -s attribute to the phpcs command.

vendor/bin/phpcs app/Core/Hooks.php -s

FILE: /Users/przemyslawhernik/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
----------------------------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------------------------
 7 | ERROR | [x] Opening brace should be on a new line (Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine)
----------------------------------------------------------------------------------------------------------------------

This specific rule has an Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine identifier, so we can take it and set it in the name attribute of the exclude tag within the ruleset that implements this rule. Please notice that we added -s argument too! Now, when we lint the files with vendor/bin/phpcs, we won't see this problem anymore.

<?xml version="1.0"?>

<ruleset name="tentypdev">
  <arg name="colors" />
  <arg value="s" />

  <file>app</file>

  <rule ref="PSR12">
    <exclude name="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine" />
  </rule>
</ruleset>

This change opens up freedom in braces placement across the codebase. The users can put them as they wish now, without any consistency which seems to be risky. The code should be consistent as much as possible! So if we don't want to put them in the new line, we should allow putting it only in the same line. Let's define it to our ruleset. It can be done by including the Generic.Functions.OpeningFunctionBraceKernighanRitchie rule.

<?xml version="1.0"?>

<ruleset name="tentypdev">
  <arg name="colors" />
  <arg value="s" />

  <file>app</file>

  <rule ref="PSR12">
    <exclude name="Squiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLine" />
  </rule>

  <rule ref="Generic.Functions.OpeningFunctionBraceKernighanRitchie" />
</ruleset>
vendor/bin/phpcs

FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Posts/Posts.php
------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
------------------------------------------------------------------------------------------
11 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/App.php
------------------------------------------------------------------------------------------
FOUND 13 ERRORS AFFECTING 13 LINES
------------------------------------------------------------------------------------------
 36 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 48 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 53 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 58 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 63 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 68 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 73 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 78 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 83 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 88 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 92 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
 97 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
106 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 13 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Widgets.php
------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
------------------------------------------------------------------------------------------
11 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Hooks.php
------------------------------------------------------------------------------------------
FOUND 4 ERRORS AND 1 WARNING AFFECTING 5 LINES
------------------------------------------------------------------------------------------
 1 | ERROR   | [x] Header blocks must be separated by a single blank line (PSR12.Files.FileHeader.SpacingAfterBlock)
 6 | WARNING | [ ] Line exceeds 120 characters; contains 122 characters (Generic.Files.LineLength.TooLong)
 8 | ERROR   | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
17 | ERROR   | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
23 | ERROR   | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Core/Config.php
------------------------------------------------------------------------------------------
FOUND 4 ERRORS AFFECTING 4 LINES
------------------------------------------------------------------------------------------
10 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
38 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
53 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
58 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Integrations/Vite.php
------------------------------------------------------------------------------------------
FOUND 4 ERRORS AFFECTING 4 LINES
------------------------------------------------------------------------------------------
 1 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
11 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
14 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
19 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Integrations/Integrations.php
------------------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 2 LINES
------------------------------------------------------------------------------------------
16 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
25 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Integrations/ESPN.php
------------------------------------------------------------------------------------------
FOUND 3 ERRORS AFFECTING 3 LINES
------------------------------------------------------------------------------------------
 1 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
13 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
26 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Teams/Teams.php
------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
------------------------------------------------------------------------------------------
11 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Templates/Resolver.php
------------------------------------------------------------------------------------------
FOUND 5 ERRORS AND 1 WARNING AFFECTING 6 LINES
------------------------------------------------------------------------------------------
 1 | ERROR   | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
26 | ERROR   | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
30 | ERROR   | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
36 | WARNING | [ ] Line exceeds 120 characters; contains 121 characters (Generic.Files.LineLength.TooLong)
45 | ERROR   | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
49 | ERROR   | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 5 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Templates/Templates.php
------------------------------------------------------------------------------------------
FOUND 4 ERRORS AFFECTING 4 LINES
------------------------------------------------------------------------------------------
 1 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
15 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
21 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
26 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Templates/Provider.php
------------------------------------------------------------------------------------------
FOUND 10 ERRORS AFFECTING 9 LINES
------------------------------------------------------------------------------------------
 1 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
17 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
22 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
22 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
27 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
28 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
29 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
32 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
34 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
39 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 10 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Assets/Resolver.php
------------------------------------------------------------------------------------------
FOUND 4 ERRORS AFFECTING 4 LINES
------------------------------------------------------------------------------------------
 1 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
13 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
27 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
36 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 4 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------


FILE: ~/Sites/tentyp.dev/footmate.pro/wp-content/themes/footmate/app/Assets/Assets.php
------------------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 2 LINES
------------------------------------------------------------------------------------------
 1 | ERROR | [x] Whitespace found at end of line (Squiz.WhiteSpace.SuperfluousWhitespace.EndLine)
15 | ERROR | [x] Opening brace should be on the same line as the declaration (Generic.Functions.OpeningFunctionBraceKernighanRitchie.BraceOnNewLine)
------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
------------------------------------------------------------------------------------------

Now, our code looks like shit 😅 There are tons of errors across all the PHP files because we used a different approach earlier. But no worry! Just run the phpcbf and your whole codebase will be formatted automatically.


How to work with PHP Code Sniffer docs?

There is one big problem that has always bothered me. How do I know which rule to use for my needs? Here, things become more complicated, because of the docs that are still in progress. I have problems finding the rules I could use to build my standards or their explanations, and I know I'm not the only one.

We can list all the sniffs in the specific coding standard by adding the -e attribute with phpcs command, but there are no explanations so we need to check them manually.

vendor/bin/phpcs --standard=PEAR -e

The PEAR standard contains 28 sniffs

Generic (9 sniffs)
------------------
  Generic.Commenting.DocComment
  Generic.ControlStructures.InlineControlStructure
  Generic.Files.LineEndings
  Generic.Files.LineLength
  Generic.Functions.FunctionCallArgumentSpacing
  Generic.NamingConventions.UpperCaseConstantName
  Generic.PHP.DisallowShortOpenTag
  Generic.PHP.LowerCaseConstant
  Generic.WhiteSpace.DisallowTabIndent

...

We can show more docs by using the vendor/bin/phpcs --standard=PEAR --generator=text command which provides more useful info but the sniff codes are not available there. If we find a useful pattern, we need to spend time and search for the sniff code again.

vendor/bin/phpcs --standard=PEAR --generator=text

---------------------------------------------
| GENERIC CODING STANDARD: CONSTRUCTOR NAME |
---------------------------------------------

Constructors should be named __construct, not after the class.

----------------------------------------- CODE COMPARISON ------------------------------------------
| Valid: The constructor is named __construct.   | Invalid: The old style class name constructor   |
|                                                | is used.                                        |
----------------------------------------------------------------------------------------------------
| class Foo                                      | class Foo                                       |
| {                                              | {                                               |
|     function __construct()                     |     function Foo()                              |
|     {                                          |     {                                           |
|     }                                          |     }                                           |
| }                                              | }                                               |
----------------------------------------------------------------------------------------------------

We can merge both and use available sniff codes to generate docs just for them with bin/phpcs --standard=PEAR --generator=text --sniffs=PEAR.Files.IncludingFile command. But let's face it - that's far away from being intuitive.

Proposition

I've decided to give it a try and propose a solution that includes sniff codes also in the documentation generated with --generator attribute to make the search process easier, but after discussion with @jrfnl - the head of the PHP Code Sniffer project - we agreed that there are also other important concerns related to docs that need to be2 handled together, so we need to think about this wider and find a more global solution.

Image

I need it now, so I've decided to create a simple tool - a bash script that iterates through all the default coding standards, gets all the sniffs available there, generates the docs for each of them, and adds more things not available by default like sniff codes, or links to sniff files in GitHub. It simply generates all the things I wished to have when starting my journey with the tool. I use it to generate markdown file which I use as a doc.

Thanks to this, I'm able to check a lot of available rules in one place one by one and search for some I want to have in my codebase - what I've done for this project. I can also find error explanations more easily and that's a huge improvement.

It's not ideal, because not all the sniffs have docs, and for sure, that's something that should be available within the official project, but that's where I want to ask you for help!

Contributions

To make the rules discoverage better and have documentation like other popular linters which helps rather than rejects, we need to work together! @jrfnl already has a lot of good ideas for handling the docs, but they are nothing without the docs themselves. The docs coverage is already nice, but there are still many of them missing.

Image

PHP Code Sniffer is installed approximately 150,000 times per day! So, if we can find 56 eager devs from this group who appreciate this tool (which isn't that many), it would address the most needed thing right now - the missing documentation for some sniffs - and open the way to make the tool better and easier to use, especially for newcomers.

Consider the tool I created as a preview of what the documentation could look like and how helpful it might be with a small group of people contributing. Your help makes the difference! If you're interested, just check out the link to the proper issue on GitHub, choose the sniffs you want to create docs for, and help make the tool better!


How to use PHP Code Sniffer with VS Code?

Let's face it. CLI usage is great, but I'm lazy, so I don't want to run linter whenever I want to check the code for potential problems. As you remember from the previous article I like to see the problems just while writing! That's where extensions come in handy. I use VS Code editor which provides a plugin for adding PHP Code Sniffer support.

At first install the extension. Then go to the plugin settings and set the following items:

  • PHP Code Sniffer: Auto Executable This setting enables searching for the phpcs script in the current and the parent directories.
  • PHP Code Sniffer: Standard This setting defines that the plugin should search for the configuration file in the current and parent directories.

Image

Now, if you open the PHP file, you'll see all the problems immediately as you write. So skipping the violations "because you haven't noticed them" is impossible now. Any red highlight means that the code is not compliant with the rules and needs to be fixed, before pushing the results to the repository. That's a great boost for you and the team. 

You can write code that is clean by default, but now you can also write code that looks like shit and then run the command to format a code for you. I use this often.

Image

Feedback

How satisfied you are after reading this article?