Voyons Ă quoi ressemblera la configuration dans un nouveau projet.
Ătape 1 - Nous initialisons le composeur (qui l'a dĂ©jĂ configurĂ©, sautez-le)
Pour ce faire, exécutez la commande à la racine de votre projet. Si vous n'avez pas installé de composer, vous pouvez vous référer à la documentation officielle de getcomposer.org
composer init
Ătape 2 - Ajouter .gitignore
###> phpstorm ###
.idea
###< phpstorm ###
/vendor/
###> friendsofphp/php-cs-fixer ###
/.php_cs
/.php_cs.cache
###< friendsofphp/php-cs-fixer ###
Ătape 3 - Ajouter les bibliothĂšques requises
composer require --dev friendsofphp/php-cs-fixer symfony/process symfony/console squizlabs/php_codesniffer
Ătape 4 - Ajouter un gestionnaire de crochet
Le gestionnaire lui-mĂȘme peut ĂȘtre Ă©crit sur n'importe quoi, mais comme l'article concerne php, nous allons Ă©crire du code dessus.
Créez un fichier dans le dossier hooks / pre-commit.php
#!/usr/bin/php
<?php
define('VENDOR_DIR', __DIR__.'/../../vendor');
require VENDOR_DIR.'/autoload.php';
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Application;
use Symfony\Component\Process\Process;
class CodeQualityTool extends Application
{
/**
* @var OutputInterface
*/
private $output;
/**
* @var InputInterface
*/
private $input;
const PHP_FILES_IN_SRC = '/^src\/(.*)(\.php)$/';
public function __construct()
{
parent::__construct('Ecombo Quality Tool', '1.0.0');
}
/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return void
* @throws \Exception
*/
public function doRun(InputInterface $input, OutputInterface $output)
{
$this->input = $input;
$this->output = $output;
$output->writeln('<fg=white;options=bold;bg=red>Code Quality Tool</fg=white;options=bold;bg=red>');
$output->writeln('<info>Fetching files</info>');
$files = $this->extractCommitedFiles();
$output->writeln('<info>Running PHPLint</info>');
if (! $this->phpLint($files)) {
throw new \Exception('There are some PHP syntax errors!');
}
$output->writeln('<info>Checking code style with PHPCS</info>');
if (! $this->codeStylePsr($files)) {
throw new \Exception(sprintf('There are PHPCS coding standards violations!'));
}
$output->writeln('<info>Well done!</info>');
}
/**
* @return array
*/
private function extractCommitedFiles()
{
$output = array();
$against = 'HEAD';
exec("git diff-index --cached --name-status $against | egrep '^(A|M)' | awk '{print $2;}'", $output);
return $output;
}
/**
* @param array $files
*
* @return bool
*
* @throws \Exception
*/
private function phpLint($files)
{
$needle = '/(\.php)|(\.inc)$/';
$succeed = true;
foreach ($files as $file) {
if (! preg_match($needle, $file)) {
continue;
}
$process = new Process(['php', '-l', $file]);
$process->run();
if (! $process->isSuccessful()) {
$this->output->writeln($file);
$this->output->writeln(sprintf('<error>%s</error>', trim($process->getErrorOutput())));
if ($succeed) {
$succeed = false;
}
}
}
return $succeed;
}
/**
* @param array $files
*
* @return bool
*/
private function codeStylePsr(array $files)
{
$succeed = true;
$needle = self::PHP_FILES_IN_SRC;
$standard = 'PSR2';
foreach ($files as $file) {
if (! preg_match($needle, $file)) {
continue;
}
$phpCsFixer = new Process([
'php',
VENDOR_DIR.'/bin/phpcs',
'-n',
'--standard='.$standard,
$file,
]);
$phpCsFixer->setWorkingDirectory(__DIR__.'/../../');
$phpCsFixer->run();
if (! $phpCsFixer->isSuccessful()) {
$this->output->writeln(sprintf('<error>%s</error>', trim($phpCsFixer->getOutput())));
if ($succeed) {
$succeed = false;
}
}
}
return $succeed;
}
}
$console = new CodeQualityTool();
$console->run();
Dans cet exemple, le code passera 3 vérifications:
- vérifier les erreurs de syntaxe
- vérifier PSR2 via le renifleur de code
PSR2 peut ĂȘtre remplacĂ© par tout autre qui prend en charge le renifleur de code. La liste des normes prises en charge peut ĂȘtre consultĂ©e en entrant la commande
vendor/bin/phpcs -i
Ătape 5 - Configuration de composer pour implĂ©menter la vĂ©rification de prĂ©-validation de dĂ©marrage automatique
Pour que le code de vĂ©rification s'exĂ©cute sur le hook prĂ©-commit, nous devons mettre le fichier avec le code que nous avons créé Ă l'Ă©tape 3, le placer dans le dossier .git / hooks / pre-commit. Cela peut ĂȘtre fait manuellement, mais il est beaucoup plus pratique d'automatiser cette question. Pour ce faire, nous devons Ă©crire un gestionnaire qui copiera ce fichier et le suspendra Ă l'Ă©vĂ©nement appelĂ© aprĂšs l'installation de composer. Pour ce faire, procĂ©dez comme suit.
5.1 CrĂ©ez le gestionnaire lui-mĂȘme qui copiera le fichier pre-commit.php dans le dossier git hooks
Créez un fichier src / Composer / ScriptHandler.php
5.2 composer
composer.json
<?php
namespace App\Composer;
use Composer\Script\Event;
class ScriptHandler
{
/**
* @param Event $event
*
* @return bool
*/
public static function preHooks(Event $event)
{
$io = $event->getIO();
$gitHook = '.git/hooks/pre-commit';
if (file_exists($gitHook)) {
unlink($gitHook);
$io->write('<info>Pre-commit hook removed!</info>');
}
return true;
}
/**
* @param Event $event
*
* @return bool
*
* @throws \Exception
*/
public static function postHooks(Event $event)
{
/** @var array $extras */
$extras = $event->getComposer()->getPackage()->getExtra();
if (! array_key_exists('hooks', $extras)) {
throw new \InvalidArgumentException('The parameter handler needs to be configured through the extra.hooks setting.');
}
$configs = $extras['hooks'];
if (! array_key_exists('pre-commit', $configs)) {
throw new \InvalidArgumentException('The parameter handler needs to be configured through the extra.hooks.pre-commit setting.');
}
if (file_exists('.git/hooks')) {
/** @var \Composer\IO\IOInterface $io */
$io = $event->getIO();
$gitHook = '.git/hooks/pre-commit';
$docHook = $configs['pre-commit'];
copy($docHook, $gitHook);
chmod($gitHook, 0777);
$io->write('<info>Pre-commit hook created!</info>');
}
return true;
}
}
5.2 composer
composer.json
"scripts": {
"post-install-cmd": [
"App\\Composer\\ScriptHandler::postHooks"
],
"post-update-cmd": [
"App\\Composer\\ScriptHandler::postHooks"
],
"pre-update-cmd": "App\\Composer\\ScriptHandler::preHooks",
"pre-install-cmd": "App\\Composer\\ScriptHandler::preHooks"
},
"extra": {
"hooks": {
"pre-commit": "hooks/pre-commit.php"
}
}
pre-update-cmd, pre-install-cmd
- avant l'installation et la mise Ă jour, l'ancien gestionnaire
post-install-cmd, post-update-cmd
est supprimé - aprÚs l'installation et la mise à jour, le gestionnaire sera défini sur pre commit
En conséquence, le fichierkik composer.json prendra la forme suivante
compositeur.json
{
"name": "admin/test",
"authors": [
{
"name": "vitaly.gorbunov",
"email": "cezar62882@gmail.com"
}
],
"minimum-stability": "stable",
"require": {},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"scripts": {
"post-install-cmd": [
"App\\Composer\\ScriptHandler::postHooks"
],
"post-update-cmd": [
"App\\Composer\\ScriptHandler::postHooks"
],
"pre-update-cmd": "App\\Composer\\ScriptHandler::preHooks",
"pre-install-cmd": "App\\Composer\\ScriptHandler::preHooks"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.16",
"symfony/process": "^5.0",
"symfony/console": "^5.0",
"squizlabs/php_codesniffer": "^3.5"
},
"extra": {
"hooks": {
"pre-commit": "hooks/pre-commit.php"
}
}
}
Exécutez à nouveau l'installation de composer afin que le fichier soit copié si nécessaire.
Tout est prĂȘt, maintenant si vous essayez de valider le code avec un style de code tordu, la console git vous en parlera.
à titre d'exemple, créons un fichier MyClass.php dans le dossier src avec le contenu suivant.
<?php
namespace App;
class MyClass
{
private $var1; private $var2;
public function __construct() {
}
public function test() {
}
}
Nous essayons de commettre et d'obtenir des erreurs de validation de code.
MBP-Admin:test admin$ git commit -am 'test'
Code Quality Tool
Fetching files
Running PHPLint
Checking code style with PHPCS
FILE: /Users/admin/projects/test/src/MyClass.php
----------------------------------------------------------------------
FOUND 5 ERRORS AFFECTING 5 LINES
----------------------------------------------------------------------
8 | ERROR | [x] Each PHP statement must be on a line by itself
10 | ERROR | [x] Opening brace should be on a new line
13 | ERROR | [x] Opening brace should be on a new line
15 | ERROR | [x] Function closing brace must go on the next line
| | following the body; found 1 blank lines before
| | brace
16 | ERROR | [x] Expected 1 newline at end of file; 0 found
----------------------------------------------------------------------
PHPCBF CAN FIX THE 5 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------
Time: 49ms; Memory: 6MB
In pre-commit line 53:
There are PHPCS coding standards violations!
Hourra, tout fonctionne.