Mal sehen, wie das Setup in einem neuen Projekt aussehen wird.
Schritt 1 - Wir initialisieren den Komponisten (wer ihn bereits konfiguriert hat, überspringt ihn)
Führen Sie dazu den Befehl im Stammverzeichnis Ihres Projekts aus. Wenn Sie keinen Composer installiert haben, können Sie sich auf die offizielle Dokumentation zu getcomposer.org beziehen
composer init
Schritt 2 - Fügen Sie .gitignore hinzu
###> phpstorm ###
.idea
###< phpstorm ###
/vendor/
###> friendsofphp/php-cs-fixer ###
/.php_cs
/.php_cs.cache
###< friendsofphp/php-cs-fixer ###
Schritt 3 - Fügen Sie die erforderlichen Bibliotheken hinzu
composer require --dev friendsofphp/php-cs-fixer symfony/process symfony/console squizlabs/php_codesniffer
Schritt 4 - Fügen Sie einen Hook-Handler hinzu
Der Handler selbst kann auf alles geschrieben werden, aber da es sich bei dem Artikel um PHP handelt, werden wir Code darauf schreiben.
Erstellen Sie eine Datei im Ordner 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();
In diesem Beispiel besteht der Code drei Prüfungen:
- Prüfung auf Syntaxfehler
- Prüfung auf PSR2 über Code-Sniffer
PSR2 kann durch jede andere ersetzt werden, die Code-Sniffer unterstützt. Die Liste der unterstützten Standards kann durch Eingabe des Befehls angezeigt werden
vendor/bin/phpcs -i
Schritt 5 - Konfigurieren von Composer für die Implementierung der Autostart-Pre-Commit-Prüfung
Damit der Bestätigungscode auf dem Pre-Commit-Hook ausgeführt werden kann, müssen wir die Datei mit dem in Schritt 3 erstellten Code in den Ordner .git / hooks / pre-commit legen. Dies kann manuell erfolgen, es ist jedoch viel bequemer, diese Angelegenheit zu automatisieren. Dazu müssen wir einen Handler schreiben, der diese Datei kopiert und an das Ereignis hängt, das nach der Installation von Composer aufgerufen wird. Gehen Sie dazu wie folgt vor.
5.1 Erstellen Sie den Handler selbst, der die Datei pre-commit.php in den Ordner git hooks kopiert
Erstellen Sie eine Datei 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
- Vor der Installation und Aktualisierung wird der alte Handler entfernt.
post-install-cmd, post-update-cmd
- Nach der Installation und Aktualisierung wird der Handler auf Pre Commit gesetzt.
Infolgedessen nimmt die Datei filekik composer.json die folgende Form an
composer.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"
}
}
}
Führen Sie die Composer-Installation erneut aus, damit die Datei bei Bedarf kopiert wird.
Alles ist fertig. Wenn Sie jetzt versuchen, den Code mit einem krummen Codestil festzuschreiben, werden Sie von der Git-Konsole darüber informiert.
Als Beispiel erstellen wir eine Datei MyClass.php im Ordner src mit dem folgenden Inhalt.
<?php
namespace App;
class MyClass
{
private $var1; private $var2;
public function __construct() {
}
public function test() {
}
}
Wir versuchen, Fehler bei der Codeüberprüfung festzuschreiben und zu erhalten.
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!
Hurra, alles funktioniert.