Improving PHP Code Quality with PHP CodeSniffer

January 31, 2020
Written by
Michael Okoko
Contributor
Opinions expressed by Twilio contributors are their own

Improving PHP Code Quality with PHP CodeSniffer

As a project grows, it becomes necessary to maintain and enforce some defined standards for the code. Such standards help achieve uniformity, readability, and maintainability, irrespective of the engineer that wrote the code. For a PHP project, one of the best ways to enforce such standards is PHP_CodeSniffer (or PHPCS for short).

PHPCS is a tool that helps detect violations of pre-defined coding standards. It also includes an additional tool that can automatically correct those violations.

Prerequisites

To complete this tutorial you will only need Composer globally installed.

About the project

PHPCS is framework-agnostic, but for simplicity, we will be using it with a simple Laravel project. The project, called “Twilio Greeter”, displays a list of common greetings depending on the language chosen by the user. You can view the complete source code here.

The project files that are of interest to us are:

  • PROJECT_ROOT/app/Http/Controllers/WelcomeController.php: Our main controller has an index method which retrieves the preferred language from the GET parameter and sends the data to the view for rendering.
  • PROJECT_ROOT/resources/views/welcome.blade.php: Displays the list passed into it from the WelcomeController.
  • PROJECT_ROOT/routes/web.php: Our project routes file

You can learn more about how the above files work and Laravel in general from the official Laravel documentation.

Setting up the project

Clone our greeter app and change into the project directory with:

$ git clone https://github.com/idoqo/twilio-greeter && cd twilio-greeter

Next, run

$ composer install

to install the project dependencies and

$ php artisan serve

to start the server. Our application is now accessible at http://localhost:8000.

Installing PHPCS

Since it’s desirable to run the PHPCS CLI as a stand-alone command, we will install it globally with the following command:

$ composer global require "squizlabs/php_codesniffer=*"

You can check your installation with:

$ phpcs

NOTE: If you get an error similar to “command not found”, ensure you place the Composer bin folder in your PATH (usually $HOME/.config/composer/vendor/bin for Linux and $HOME/.composer/vendor/bin for MacOS).

Our Preferences

Our application works fine after cloning, but the coding style could use some improvements. PHPCS supports lots of coding standards out of the box such as PSR12, PSR2, PEAR, and Zend. You can also create your own rules if they are all found wanting.

For our use case, we want some rules such as:

  • Visibility of all properties/methods must be explicitly declared (PHP defaults to public visibility if none is provided).
  • Opening and closing braces for methods should be on a separate line.
  • Function calls that span multiple lines should have only one argument per line e.g
<?php

$message->send(

$arg1,

$arg2,

$arg3

);

Fortunately for us, our preferences are conventional and have been covered by the PSR12 standard, so we will just go ahead and use the PSR12 as our base configuration.

Configuring PHPCS for our Project

To start, let’s create a new file called phpcs.xml in our project root directory with:

$ touch phpcs.xml

and add the following:

<?xml version="1.0"?>

<ruleset  name="PHP_CodeSniffer">

<description>PHPCS configuration file.</description>
<!-- check all files in the app directory, feel free to add more files with:
<file>FOLDER NAME</file>
-->
<file>app</file>

<!-- exclude our migrations directory from the violation check-->
<exclude-pattern>*/migrations/*</exclude-pattern>

<!-- ignore warnings and display ERRORS only -->
<arg  value="np"/>

<!-- Our base rule: set to PSR12-->
<rule  ref="PSR12"/>

</ruleset>

The code above has been commented to provide some explanation, but you can look up the PHPCS wiki to see the different options you can provide.

Running our first test

At this point, our project is ready and we can test for violations now. In the root directory, run:

$ phpcs

If all went well, you should see an output similar to:

.............E.......... 24 / 24 (100%)


FILE: /home/PATH_TO_PROJECT/twilio-greeter/app/Http/Controllers/WelcomeController.php

--------------------------------------------------------------------------------------------------------------

FOUND 5 ERRORS AFFECTING 3 LINES

--------------------------------------------------------------------------------------------------------------

1 | ERROR | [x] Header blocks must be separated by a single blank line

8 | ERROR | [ ] Visibility must be declared on method "showGreetings"

8 | ERROR | [x] Opening brace should be on a new line

18 | ERROR | [ ] Visibility must be declared on method "greetings"

18 | ERROR | [x] Opening brace should be on a new line

--------------------------------------------------------------------------------------------------------------

PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY

--------------------------------------------------------------------------------------------------------------

  

Time: 208ms; Memory: 6MB

Fixing as we go.

The report above included the files and the line number in which we went against the rules. For instance, we need to specify the method visibility on line 8 and move the opening brace on line 18 to a new line.

A quick way out would be to run:

$ phpcbf

in the project directory and PHPCS will automatically try to fix the violations marked with [x], but let’s attempt to fix them ourselves.

From our report, the only file we need to clean up is app/Http/Controllers/WelcomeController.php so open it and make the following corrections. First, we add a blank line between line 1 and 2 so it looks like the following:

<?php

namespace  App\Http\Controllers;

...

Then, we specify the visibility for the showGreetings method and move the opening brace to a new line, so replace:

function  showGreetings(Request  $request){

...

with:

public  function  showGreetings(Request  $request)
{

...

Finally, we mark our greetings method as private (since we don’t need to call it outside of the WelcomeController class). We’ll also move it’s opening brace to a new line too as follows. Replace:

function  greetings($language) {

...

With:

private  function  greetings($language)
{

...

NOTE: The clean version of the project is on the tidied branch and you can view it by checking out the tidied branch like so:

$ git checkout tidied

Now, run phpcs again and our errors should have disappeared.

Conclusion

Code guidelines help to reduce the cognitive load required to work in a project with multiple developers, and PHPCodeSniffer does a good job of ensuring adherence to pre-set standards. If you’re looking to build your own custom rules, the existing rulesets are a good place to start.

I hope you enjoyed the post and if there are any issues or questions, please feel free to reach out to me via Email or on Github.

Additional Reading

To further your education, check out the related topics: