This very simple script will run these checks each time you commit:
- PHP Internal Linter to check your code for syntax errors
- PHP Code Sniffer to check for coding standard (PSR-2)
- PHPStan to analyse the code and find bugs
Overall it takes a few seconds and it analyses only the staged files - those in green when you do a git status
.
If a single check fails the error message is displayed and the commit is aborted.
Example:
[1/3] php lint OK!
[2/3] code sniffer OK!
[3/3] phpstan NOK!
1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%
------ ---------------------------------------------------------------------
Line CanSendInvitation.php
------ ---------------------------------------------------------------------
14 Parameter $lol of method App\Rules\CanSendInvitation::__construct()
has invalid typehint type App\Rules\Noob.
------ ---------------------------------------------------------------------
[ERROR] Found 1 error
Step 1: requirements
You're going to need some packages to validate your code so go ahead and install:
composer install --dev phpstan/phpstan
composer install --dev squizlabs/php_codesniffer
Step 2: create the hook
In .git/hooks/pre-commit
write:
#!/usr/bin/env bash
# get bash colors and styles here:
# http://misc.flogisoft.com/bash/tip_colors_and_formatting
C_RESET='\e[0m'
C_RED='\e[31m'
C_GREEN='\e[32m'
C_YELLOW='\e[33m'
function __run() #(step, name, cmd)
{
local color output exitcode
printf "${C_YELLOW}[%s]${C_RESET} %-20s" "$1" "$2"
output=$(eval "$3" 2>&1)
exitcode=$?
if [[ 0 == $exitcode || 130 == $exitcode ]]; then
echo -e "${C_GREEN}OK!${C_RESET}"
else
echo -e "${C_RED}NOK!${C_RESET}\n\n$output"
exit 1
fi
}
modified="git diff --diff-filter=M --name-only --cached | grep \".php$\""
ignore="resources/lang,resources/views,bootstrap/helpers,database/migrations,bin"
phpcs="vendor/bin/phpcs --report=code --colors --report-width=80 --standard=PSR2 --ignore=${ignore}"
__run "1/3" "php lint" "${modified} | xargs -r php -l"
__run "2/3" "code sniffer" "${modified} | xargs -r ${phpcs}"
__run "3/3" "phpstan" "${modified} | xargs -r vendor/bin/phpstan analyse"
The line
ignore="resources/lang,resources/views,bootstrap/helpers,database/migrations,bin"
is project specific. It's the comma separated list of paths to ignore in the PHP Code Sniffer analysis. Typically, you add the paths for which the PSR-2 makes no sense, like configuration or translation files.
You may change it to whatever you want.
My team has been using and refining this script for years and it has saved us countless hours in refactoring. The sooner you detect errors the better.
Our real script includes more tests that are specific to our app like unit & behavioral test to ensure you broke nothing. I'm sure with a little imagination you are capable to adapt the script to your project.
I suggest you play around with it and share what you find out in the comments.
A usual don't forget to like and comment, that keeps me motivated to write more content for you!
Happy coding!
Top comments (5)
1) What's the difference between code sniffer and editor config? Is code sniffer a more language-specific form of formatting i.e. Looks into language specific things like naming convention?
2) Why do we need to run
php lint
first? Isn't that what the first level of php-stan/psalm does?Good post!
It's a great sample to start with.
I have tried this but getting below error
xargs: ./vendor/bin/phpcs: No such file or directory
it is working directly but not from pre-commit
Add PHPCS as a dev dependency with
composer require --dev squizlabs/php_codesniffer
.