Pragmatism in the real world

Checking your code for PSR-2

Most of the projects that I work on follow the PSR-2 coding style guidelines. I prefer to ensure that my PRs pass before Travis or Jenkins tells me, so let’s look at how to run PSR-2 checks locally.

PHP_CodeSniffer

My preferred tool for checking coding styles in PHP is PHP_CodeSniffer. This is command line tool, phpcs, that you can run against any file.

PHP_CodeSniffer can test against a number of standards. The default is PEAR, so you must use the command line switch --standard=PSR2 in order for it to check against the right one.

Let’s take an example from joind.in‘s web2 project:

$ phpcs --standard=PSR2 BaseApi.php 

FILE: ...joind.in/joindin-vm/joindin-web2/app/src/Application/BaseApi.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 11 | ERROR | [x] Expected 1 space after closing parenthesis; found 9
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 70ms; Memory: 6Mb

This is the code that’s wrong:

if (isset($config['apiUrl']))
{
    $this->baseApiUrl = $config['apiUrl'];
}

The opening brace is in the wrong place.

If there is a note that PHPCBF can fix some validations automatically, then you can run the phpcbf command line tool to automatically fix your code:

$ phpcbf --standard=PSR2 BaseApi.php 
Changing into directory .../joindin-vm/joindin-web2/app/src/Application
Processing BaseApi.php [PHP => 1452 tokens in 186 lines]... DONE in 52ms (1 fixable violations)
        => Fixing file: 0/1 violations remaining [made 3 passes]... DONE in 163ms
Patched 1 file
Time: 246ms; Memory: 8Mb

And phpcbf has changed the code to be compliant:

if (isset($config['apiUrl'])) {
    $this->baseApiUrl = $config['apiUrl'];
}

Obviously, not all violations can be automatically fixed, but a good number can be.

Automating with Phing

Generally you want to be able to run phpcs across all your source files without too much effort and also get your CI tool to do the same. My preferred choice here is to use Phing.

Each command within a Phing build.xml file is called a target. The PHP_CodeSniffer target for the web2 project is:

<target name="phpcs">
 <phpcodesniffer standard="PSR2"
      description="Run PSR2 standards over the codebase"
      haltonerror="true">
   <fileset dir="${basedir}/app">
     <include name="**/*.php"/>
   </fileset>
   <fileset dir="${basedir}/tests">
     <include name="**/*.php"/>
   </fileset>
   <formatter type="full" usefile="false"/>
 </phpcodesniffer>
</target>

With this target we run phpcs over all PHP files in the `app` and `tests` directories. We run it like this:

$ phing phpcs

As Phing is simply a build tool, the error output is the same format as earlier.

Editor integration

I use Vim and Sublime Text 3, which both have plugins for checking syntax.

Syntastic for Vim

Syntastic is a great plugin for Vim that checks syntax for any language that you can think of. Install it using your preferred method and then for PHP linting and PSR-2 checking set up in your .vimrc like this:

" Syntastic
let g:syntastic_php_checkers=['php', 'phpcs']
let g:syntastic_php_phpcs_args='--standard=PSR2 -n'

You can also add Syntastic summary information to the status line using %{SyntasticStatuslineFlag()}.

The display looks like this (Yes, I like white backgrounds for editing, sorry!):

Syntastic PSR2 checking

When you save the file, Syntactic runs the checkers that you’ve set up, php -l and phpcs --standard=PSR2 -n in this case and displays any errors with a red S> in the gutter and if you’ve enabled it, a summary in the status line. When your cursor is on that line, then the error is displayed at the very bottom.

SublimeLinter for Sublime Text 3

The SublimeLinter project does for Sublime Text 3. You need to install “SublimeLinter”, “SublimeLinter-php” and “SublimeLinter-phpcs” via Package Control as each linter is separate.

Configure by selecting the Preferences -> Package Settings -> SublimeLinter -> Settings - User menu item. My settings are:

{
    "user": {
        "delay": 0.5,
        "linters": {
            "php": {
                "@disable": false,
                "args": [],
                "excludes": []
            },
            "phpcs": {
                "@disable": false,
                "args": [
                    "-n"
                ],
                "excludes": [
                    "*.phtml",
                    "*.twig"
                ],
                "standard": "PSR2"
            }
        }
    }
}

This sets up SublimeLinter to check half a second after you stop typing and then it will highlight any errors:

SublimeLinter PSR2 checking

You get a marker in the left hand gutter and an outline around the detected error. Placing your cursor on that line displays the error in the status bar.

To sum up

Ensuring that your code matches the coding style for your project is very easy. If you run phpcs locally and fix any issues before you submit your PR, then the project maintainers will love you!

10 thoughts on “Checking your code for PSR-2

    1. Thanks Gary. I was pretty sure that the major PHP IDEs have support, but as I don't use them, I wasn't comfortable commenting on what was possible.

    2. I'd thought of writing up a brief post re: phpstorm, but Gary beat me to it. Great post Rob. Perhaps you could be my mentor for coding with Vim.

  1. Starting with the 2.0 series of PHPCS, you can also create a phpcs.xml configuration file to define the rules you want to use, and directories and files to scan (and/or exclude). A full example is here:

    http://pear.php.net/manual/en/package.php.php-codesniffer.annotated-ruleset.php

    The nice side-benefit to using this is that you can then just run phpcs directly without arguments in the directory containing the config file, without requiring another tool to configure how it runs.

    1. Seems really focused on being PSR1/2 and Symfony specific. PHPCodeSniffer can do a lot of different formats and has a good ecosystem of custom rules, plus is far more mature. PHPCodeSniffer can also handle css and js files too, which is pretty cool to have all your rules in one place. PHPCSFixer may be simpler but the tradeoffs are clear.

  2. That's great stuff Rob, and thanks for touching on Syntastic.

    If specifying the coding standard for PHPCS is getting old quick, and you'd rather not set up an alias for it, you can save it as a configuration setting via:

    $ sudo phpcs –config-set standard PSR2

    On my machine, this gets saved to /usr/share/php/data/PHP_CodeSniffer/CodeSniffer.conf which is why I used sudo to ensure that file could be modified.

Comments are closed.