(I wonder if I can make that title any geekier?)

Let’s start by describing what the parts of this task are, and what we are doing today. The overall goal is this:

We want all of our application files to meet a certain code style, and so to make it less cumbersome to enforce this, we’d like to use PHP-CS-Fixer (https://github.com/FriendsOfPHP/PHP-CS-Fixer).

However, trying to get the whole team to always remember to run this before pushing code is like herding cats, so we’d also like to make that an automated part of the commit process.

Have no fear! What I’ll show you below is one way to set that all up that will make use of the git pre-commit hook. We’ll do this to set up PHP-CS-Fixer, but it will be obvious how to set this up to automate virtually anything at all.

Let’s start by taking a clean file or framework to play with (I’m going to use a Laravel setup I have for this sort of thing) and creating an empty git repository with git init . (You can feel free to use anything existing, as long as you know what you are working with.) There is no need to have a remote repository set up for this — we won’t be doing any pushing, only committing.

I hate those “outside the scope of this post” tutorials, but I am going to have to ask you to go ahead and set a few things up for your self — composer (https://getcomposer.org) for starters, and then pull in the PHP-CS-Fixer (https://github.com/FriendsOfPHP/PHP-CS-Fixer) package.

PHP-CS-Fixer has a lot of options and ways of running; we’re going to stay simple and just set up a .php_cs file and run locally from our vendor/bin . So put this file in your root:

<?php // file ".php_cs"



use PhpCsFixer\Config;

use Symfony\Component\Finder\Finder;



$finder = Finder::create()

->in(__DIR__)

->name('*.php')

->ignoreDotFiles(true)

->ignoreVCS(true);



return Config::create()

->setRules([

'@PSR2' => true,

'array_indentation' => true,

'array_syntax' => ['syntax' => 'short'],

'binary_operator_spaces' => true,

'blank_line_after_namespace' => true,

'blank_line_before_return' => true,

'braces' => true,

'class_definition' => true,

'method_chaining_indentation' => true,

'no_extra_consecutive_blank_lines' => true,

'no_multiline_whitespace_before_semicolons' => true,

'no_short_echo_tag' => true,

'no_spaces_around_offset' => true,

'no_unused_imports' => true,

'no_whitespace_before_comma_in_array' => true,

'not_operator_with_successor_space' => true,

'ordered_imports' => ['sortAlgorithm' => 'length'],

'trailing_comma_in_multiline_array' => true,

'trim_array_spaces' => true,

'single_quote' => true,

])

->setFinder($finder);

Then from the commandline run php vendor/bin/php-cs-fixer fix . That’s the simplest form that will work, I believe, to keep thing…er, simple. If anything is not running correctly, stop now and make sure to fix it. Here’s an excellent article from Billie Thompson (https://dev.to/purplebooth/coding-standards-in-php-using-php-cs-fixer) that explains more about what this tool does, or ask the nice people on the internet.

So this is now setup to force your files to conform to PSR-1 and PSR-2 (by default). Go into a file and make some changes that violate your sense of everything good in the world — say, for example, putting an opening bracket on the same line as the function keyword — and then run this to see that it has been fixed. Magic! Clean again.

The old Scared of Auto-Jumbly Scripty Things me would have been happy to stop right there, prolly setting an alias on my git commits or something to make sure I don’t constantly forget to run it, but forgetting most of the time anyway and being constantly moaned at. New me will automate this.

Old Me, facing the prospect of writing an Auto-Jumbly Scripty Thing

As I said at the beginning, there are myriad ways of doing this sort of thing, but what we are going to do is use an npm package called “Husky” (https://libraries.io/npm/husky) that is designed to tap into the existing Git Hooks (https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). After you go ahead and install Husky, I want you to open your .git/hooks directory and…OMG, look at all those hook files!

Don’t worry — we won’t be working with those directly. Most of them were created when you installed Husky, and node.js will know what needs to be done (if you want to open the pre-commit file, you’ll see that Husky did, indeed, create it.) Instead, we’ll go into our package.json file and give Husky the commands we want:

"husky": {

"hooks": {

"pre-commit": "vendor/bin/php-cs-fixer fix && git add ."

}

},

Notice there is no php in the command!

Let’s test it out. Go back and make an eyesore of that file you used before, then do a quick check with git status to see that it is waiting to be staged. When you’re ready, do NOT use git add . ; just commit with:

git commit -m "Committing prettified version of file"

and check the status again. It has been staged; the file has been cleaned to be PSR compliant. You’ve done it!

Notice that we piped the git add . — since this is pre-commit, what we are doing is first fixing the file styling and staging anything that has been changed, and then committing it all.

This example stuck to the narrowest working path that I could, but as you poke around the documentation of both Husky & Git Hooks you’ll see there are ways of customizing virtually every step until you find something that meets your needs.

Hope that helped!