Русский
Русский
English
Статистика
Реклама

Автоматическая проверка кода за 5 минут

Данная инструкция показывает как автоматизировать проверку на code style в вашем php проекте.

Давайте посмотрим как будет выглядеть настройка в новом проекте.

Шаг 1 Делаем инициализацию composer (у кого он уже настроен, пропускаем)


Для этого в корне вашего проекта запускаем команду. Если у вас не установлен composer, то можете обратиться к официальной документации getcomposer.org

composer init

Шаг 2 Добавляем .gitignore


###> phpstorm ###.idea###< phpstorm ###/vendor/###> friendsofphp/php-cs-fixer ###/.php_cs/.php_cs.cache###< friendsofphp/php-cs-fixer ###

Шаг 3 Добавляем нужные библиотеки


composer require --dev friendsofphp/php-cs-fixer symfony/process symfony/console  squizlabs/php_codesniffer

Шаг 4 Добавляем обработчик хука


Сам обработчик можно написать на чем угодно, но так как статься про php то будем писать код на нем.

Создаем файлик в папочке hooks/pre-commit.php
#!/usr/bin/php<?phpdefine('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();



В данном примере код будет проходить 3 проверки:
проверка на синтаксические ошибки
проверка на PSR2 через code sniffer

PSR2 можно заменить на любой другой который поддерживает code sniffer. Список поддерживаемых стандартов можно увидеть введя команду

 vendor/bin/phpcs -i


Шаг 5 Конфигурируем composer для реализации автозапуска проверки на pre-commit


Для того чтобы код проверки запускался на pre commit хук нам необходимо положить файлик с кодом, который сделали в 3 пункте положить в папку .git/hooks/pre-commit. Это можно сделать вручную но куда удобнее это дело автоматизировать. Для этого нам нужно написать обработчик, который будет копировать этот файлик и повешать его на событие которые вызывается после composer install. Для этого делаем следующее.

5.1 Создаем сам обработчик который будет копировать файлик pre-commit.php в папку хуков гита


Создаем файлик src/Composer/ScriptHandler.php
<?phpnamespace 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 перед install и update удаляется старый обработчик

post-install-cmd, post-update-cmd после install и update будет устанавливаться обработчик на pre commit

В итоге файлкик composer.json примет следующий вид

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"        }    }}



Запускаем еще раз composer install чтобы файлик скопировался куда надо.

Все готово, теперь если вы попытаетесь закомитить код с кривым code style то git console вам об этом скажет.

В качестве примере давайте создадим в папке src файлик MyClass.php по следующим содержаением.

<?phpnamespace App;class MyClass{    private $var1; private $var2;    public function __construct() {    }    public function test() {    }}

Пытаемся закомитить и получаем ошибки проверки кода.

MBP-Admin:test admin$ git commit -am 'test'Code Quality ToolFetching filesRunning PHPLintChecking code style with PHPCSFILE: /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: 6MBIn pre-commit line 53:                                                  There are PHPCS coding standards violations!                      

Ура, всё работает.
Источник: habr.com
К списку статей
Опубликовано: 22.03.2021 16:16:43
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Php

Symfony

Инструменты для веб-разработки

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru