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.sample → pre-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!
Post your comment
Comments
Posted by Akif Turan, 13/03/2017 8:58pm (8 years ago)
No one has commented on this page yet.
RSS feed for comments on this page | RSS feed for all comments