Formatting PHP Files with Git Hooks

When working on a PHP project with multiple developers, maintaining a consistent code style is crucial for readability, maintainability, and collaboration. One effective way to ensure consistent formatting across your codebase is by using Git hooks to automate the process.

What Are Git Hooks?

Git hooks are scripts that are executed before or after specific Git commands, such as git commit, git push, and git merge. These hooks allow you to automate processes and enforce certain rules, such as code formatting or running tests.

For PHP projects, we can use a Git hook to automatically format PHP files before they’re committed to the repository. This ensures that every commit adheres to a predefined code style, without relying on developers to format their code manually.

Prerequisites

To follow along, you’ll need:

  • A PHP project with Git initialized.
  • Composer (PHP’s dependency manager) installed on your system.
  • A PHP code formatter like PHP-CS-Fixer.
  • Basic understanding of how Git works, specifically with hooks.

Step 1: Install PHP-CS-Fixer

PHP-CS-Fixer is a tool that automatically formats PHP files to comply with a specific coding standard. You can easily install it using Composer.

Run the following command to install PHP-CS-Fixer:

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

This will install PHP-CS-Fixer as a development dependency in your project. Once installed, you can run PHP-CS-Fixer from the command line to fix code formatting issues.

Step 2: Create a Git Hook

Git hooks are stored in the .git/hooks directory of your repository. The hook we’ll be working with is the pre-commit hook, which is executed before a commit is made.

1. Navigate to the .git/hooks directory:

cd .git/hooks

2. Create the pre-commit hook:

You can create a pre-commit file inside the .git/hooks directory to trigger PHP-CS-Fixer before each commit. If a pre-commit hook already exists, you can modify it.

Here’s how you can create a new pre-commit hook:

touch pre-commit
chmod +x pre-commit

3. Edit the pre-commit file:

Open the pre-commit file with your preferred text editor. In this file, we’ll add the script to run PHP-CS-Fixer.

Here’s a basic pre-commit hook script to format PHP files:

#!/bin/sh

# Run PHP-CS-Fixer to fix PHP files
./vendor/bin/php-cs-fixer fix --config=.php_cs.dist

# Check if there were changes after formatting
if ! git diff --exit-code; then
  echo "PHP files were automatically formatted. Please review the changes."
  exit 1
fi

Explanation:

  • The script runs PHP-CS-Fixer using the configuration file .php_cs.dist. You can customize this file to define the coding standards you want to follow.
  • After running PHP-CS-Fixer, the hook checks if any changes were made to the files. If changes were made, it will display a message and prevent the commit until the developer reviews the formatting changes.

Step 3: Configure PHP-CS-Fixer

You can customize PHP-CS-Fixer’s behavior by adding a configuration file to your project. Create a .php_cs.dist file in the root directory of your project with the following content:

<?php

use PhpCsFixer\Config;

return (new Config())
    ->setRiskyAllowed(true)
    ->setRules([
        '@PSR2' => true,
        'binary_operator_spaces' => ['operators' => ['=>' => 'align']],
        'array_syntax' => ['syntax' => 'short'],
        'no_trailing_whitespace' => true,
        'no_unused_imports' => true,
    ])
    ->setFinder(
        PhpCsFixer\Finder::create()
            ->in(__DIR__)
            ->exclude(['vendor'])
    );

This configuration ensures that PHP-CS-Fixer will follow the PSR-2 coding standard, which is widely adopted in the PHP community, and enforces other rules like removing trailing whitespace and unused imports.

Explanation:

  • @PSR2: This rule enforces the PSR-2 coding standard.
  • binary_operator_spaces: Ensures operators like => are aligned.
  • array_syntax: Enforces the use of short array syntax [] instead of array().
  • no_trailing_whitespace: Removes unnecessary whitespace from the end of lines.
  • no_unused_imports: Removes unused imports from your code.

Step 4: Test the Git Hook

Once everything is set up, make a change to any PHP file in your project and try to commit it:

git add .
git commit -m "Test pre-commit hook"

The pre-commit hook should run automatically and format your PHP files according to the configuration in .php_cs.dist. If any files were modified by PHP-CS-Fixer, the commit will be blocked, and you’ll be asked to review the changes.