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.

You can leave a response, or trackback from your own site.

7 Responses to “Symfony2: Checking Coding Standards”

  1. chEbba says:

    There is a plugin from Benjamin Eberlei for Netbeans.
    And you can find a tutorial on http://www.amaxus.com/cms-blog/coding-standards-netbeans-php-codesniffer
    Work for me under Ubuntu and Netbeans 7

  2. Luis says:

    how does your header for the build.xml looks like?

    Mine looks like this

    however whenever i try to run it from the top it gives me

    Target ‘app’ does not exist in this project.

    But whenever i run it from the target it runs correctly.

    Any hint? Thanks!

  3. Luis says:

    also I had to use PHP_CodeSniffer-18247.patch.patch.txt

  4. miller says:

    Looks like you cannot post xml in these comments at the moment, I will have a look into this. So without being able to see it I’m not sure what the problem is. You can specify a default target which will be run if you do not specify a target at the command line, does your default target match up with the name of your target?

  5. Luis says:

    Hi Miller,

    what i meant is that the lines you have for your target and all is wrapped by some xml top tags and also a project tag if I am not mistaken. There is a project name or somethinkg like this

    tag start project name=”start_page” basedir=”.” default=”app” tag ends

    so whenever i try to run the entire thing and not just a target, or I guess running all the targets… it gives me an error complaining that there is not such a default project or something.

    Perhaps you work in phpstorm? i do, and I get a tree formed and the root tree on the panel have the options to be run. So that is how i handle phing. It has a console where I can see the command run and the output.

    Please let me know, thanks.

  6. Luis says:

    different syntax for phing i guess

    I passed the ant script from sebastian into phing then set the build to call phing rather than ant:

    https://github.com/cordoval/FormModelProjectBundle/blob/master/buildphing.xml

    This works with phpstorm, did not know if phpstorm supported ant, but anyway it works nicely, so no more typing commands.

Leave a Reply

Please use [code] and [/code] around any source code/html/xml you wish to include in a comment.

Subscribe to RSS Feed Follow me on Twitter!