Symfony2: Checking Coding Standards

Note: the coding standards used by Symfony2 have changed since this post was written, you can read more about this in my post Symfony2: Coding Standards Update

Coding standards are good, they are especially important on large projects with many collaborators such as Symfony2. Obviously very messy code with no consistency is a problem, it is difficult to read, making it hard to maintain.

There is not only one way to write well formatted code and not everyone agrees on which is the best way to format certain things to say the least. This means that it is important to not just write tidy code but code that is consistent with the code of everyone else involved in the project. So projects such as Symfony2 standardise on a particular set of coding standards which you should adhere to if you are contributing to the project or in Symfony2's case writing third party bundles. You may also want to make sure that any code you write for an application based on Symfony2 meets the same standards.

The Symfony2 coding standard follows the Pear/ZendFramework standards with a few differences. You can read a detailed list of the standards in the contributing section of the documentation.

PHP_CodeSniffer

Whilst a great starting point trying to actually remember all that when coding will be difficult. Fortunately you can use the PHP_CodeSniffer tool to find any where in your code that does not meet the standards.

You can install PHP_CodeSniffer using Pear:

pear install PHP_CodeSniffer

The Symfony2 coding standard is not included, you can obtain it from Git though, the README.md goes through how to install the custom standard.

So if you had a file with the following code in it:

if (!$testimonial)
{
    throw new NotFoundHttpException('Testimonial not found.');
}

You can then run PHP_CodeSniffer at the command line to get a report of any errors or warnings, against this file:

phpcs --standard=Symfony2 ./TestimonialController.php

This outputs the following report:

FILE: ...fony/src/LimeThinking/SpringBundle/Controller/TestimonialController.php
--------------------------------------------------------------------------------
FOUND 1 ERROR(S) AFFECTING 1 LINE(S)
--------------------------------------------------------------------------------
 51 | ERROR | Expected "if (...) {\n"; found "if (...)\n        {\n"
--------------------------------------------------------------------------------

Time: 0 seconds, Memory: 2.50Mb

You can also run PHP_CodeSniffer against directories rather than individual files.

Phing

As well as running PHP_CodeSniffer manually you may want to run in from a build tool such Phing you can then run PHP_CodeSniffer along with other tools such as PHPUnit, PHPDepend with one CLI command rather than having to run each separately. There is a built in Phing task for PHP_CodeSniffer that you can use for this. The following will provide a full report on my LimeThinkingSpring bundle:

<target name="phpcs"
        description="Provides full PHP_CodeSniffer test results.">
    <phpcodesniffer standard="Symfony2">
         <fileset dir="/path/to/project/Symfony/src/LimeThinking/SpringBundle">
             <include name="**/*.php"/>
         </fileset>
    </phpcodesniffer>
</target>

If you also include in the build file other targets for other tests and a target that depends on them:

<target name="tests"
        description="Run various tests"
        depends="phpunit, phpcpd, phpcs"/>

you can run them altogether with simple command:

phing tests

If you prefer to use Ant for builds then it does not have a built in task but you can still use an Exec task to call PHP_codeSniffer:

<target name="phpcs" description="Provides full PHP_CodeSniffer test results.">
    <exec executable="phpcs">
        <arg line="--standard=symfony2 /path/to/project/Symfony/src/LimeThinking/SpringBundle" />    
    </exec>
</target>

Jenkins

As simple as it is to run the tests using Phing, you still need to remember to do it. If you are using a tool such as Jenkins for Continuous Integration then you can use it to run these sorts of tests automatically when you commit changes to version control.

There are instructions for setting up Hudson with Phing, Jenkins is a fork of Hudson so you will need to make some changes to the instructions. Whilst my preference is for Phing it is currently easier to set up Jenkins for PHP CI using Ant using Sebastian Bergmann's excellent Template for Jenkins Jobs for PHP Projects.

The most useful way of integrating PHP_CodeSniffer into Jenkins is to have it output a checkstyle report. You can then use the checkstyle Jenkins plugin to display the results in the build report. This includes details of any errors and warnings. It also displays a graph of the number of errors and warnings across builds:

Example of Checkstyle graph in Jenkins

Eclipse Integration

As well as catching any errors by running PHP_CodeSniffer against your code it is possible to integrate it into some IDEs to provide real time checking so you can see any violations as you code. Here I will look at implementing it in Eclipse. There is a plugin to integrate PHP_CodeSniffer which is part of the PHP Tool Integration project, you can find more information and installation instructions here.

Again you will need to add in the Symfony2 standard, instructions for doing this are in the configuration section.

Now in Eclipse you will get immediate feedback on any coding standards violations. So our code from before will look like this:
Example of Coding Standards violation being highlighted in Eclipse

This allows you to correct any violations as you code rather than afterwards by running the PHP_CodeSniffer later.

Note: at the time of writing Symfony2 is at Release Candidate stage and moving towards a stable release so they are looking for bug fixes only and not Pull Requests with coding standards changes.