Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

 

Hooked on standards

In today's blog post, SilverStripe Principal Developer, Chris Pitt, talks about coding standards and why he is hooked on them.

Read post

I love coding standards. They keep things looking the same, no matter how many team members write the code I need to review and maintain. That's ultimately what they're best at.

In his book Clean Code, Robert Martin talks about the importance of reading code vs. writing code; that what we write needs to be entirely focussed on being easy to read and understand; that writing something succinctly is a waste of time if the effort makes understanding it harder.

PHP linting and fixing

Admittedly, code standards play only a small part in this. And adopting something like PSR-2 (the PHP community's de facto code formatting standard) can lead to a lot of repetitive work. That is unless it can be automated.

Integrated development environments (like PHPStorm) have built-in support for automating various aspects of standards compliance, but not everyone uses these. And what about when an edit is made in a strange environment, like a remote server?

Luckily, others have solved this problem. Take, for instance, the php-cs-fixer library, installed with:

composer require --dev friendsofphp/php-cs-fixer

This library provides a binary of sorts, aimed at listing and correcting errant PHP code style:

vendor/bin/php-cs-fixer fix src

It scans the PHP files (in src) and fixes their style as best it can.

Git hooks

We can take it a step further by introducing Git hooks. Before we look at that code, let's talk a bit about Git:

git diff --cached --name-status --diff-filter=ACM

Inside a git repository, if you add files for a commit, the above command will list them. It's like saying: "Tell me all the files that I'm about to commit to the repository".

Given this list, it's possible to find all PHP files we're about to introduce, and run them through the linter/fixer:

#!/usr/bin/env php
<?php

exec(
  "git diff --cached --name-status --diff-filter=ACM",
  $output
);

foreach ($output as $line) {
  $file = trim(substr($line, 1));
  $extension = pathinfo($file, PATHINFO_EXTENSION);

  if ($extension === "php") {
    $escaped = escapeshellarg($file);
    exec("php -l {$escaped}", $output, $return);

    if ($return != 0) {
        echo implode("\n", $output), "\n";
        exit(1);
    }

    $binary = "vendor/bin/php-cs-fixer";
    exec("{$binary} --using-cache=no fix {$file}");
    exec("git add {$file}");
  }
}

exit(0);

The irony in fitting this code to a narrower screen is that it doesn't conform to PSR-2!

This script can be run (after a call to chmod +x pre-commit), and it'll go through all files about to be committed, linting and fixing them. Once they're listed and fixed, they're added back to the index, so that they can be committed.

Run as a pre-commit Git hook, this means all PHP files are automatically checked and corrected before a commit can be successfully completed. If there are syntax errors in your code, they can't be committed to the repository.

This file needs to be created as .git/hooks/pre-commit. You can find example hook files in that folder, but none of them are automatically enabled, as the file names must match the events they target: pre-commit.samplepre-commit.

You can learn more about Git hooks in the documentation.

JS linting and fixing

If your project includes a bit of JS, and you'd like to apply code style formatting to that, you could use something like ESLint:

npm install --save-dev babel-eslint
npm install --save-dev eslint
npm install --save-dev eslint-config-airbnb
npm install --save-dev eslint-plugin-import
npm install --save-dev eslint-plugin-jsx-a11y
npm install --save-dev eslint-plugin-react

This assumes you're going for AirBnB JS code style. You can, of course, configure ESLint to your preferred standard.

It would also help if you configured ESLint to allow global variables (like window and document):

{
    "extends": "airbnb",
    "env": {
        "browser": true,
        "node": true
    }
}

Since we already have a PHP Git hook file, we need to run ESLint via PHP:

exec("node_modules/.bin/eslint assets/js --fix");

Happy coding!

About the author
Christopher Pitt

Chris works in the bespoke team, at SilverStripe. He helps build and maintain many of the modules used in SilverStripe applications. He also teaches; speaking at local user groups and international conferences, and through technical blog posts and books.

He also enjoys building robots and connecting those to circuits inside Minecraft. When the machines take over, he hopes this will buy him some time to formulate a plan of escape.

Post your comment

Comments

  • I like that. Thank you

    Posted by Akif Turan, 13/03/2017 8:58pm (6 months ago)

RSS feed for comments on this page | RSS feed for all comments

Like what you have read?

Sign up for our weekly blog digest sent to your inbox.

Subscribe