hayasaki
Table of Contents
ゴール
git commit のフックで自動的に PHPStan を利用した静的解析が実行出来るようになること。
環境
- PHP7.2
- composer が使える
PHPStan とは?
Qiita [PHP] 静的解析ツール PHPStan の機能概要
PHPStan で始める PHP のための静的解析 #phperkaigi
基本的な使い方は URL 先やググったら沢山情報がでるのでそちらにお任せしますが、要は静的解析が出来ます。
(PHPMD や PHPlint に近いかな)
ということで導入してみます。
私は毎回コマンドを叩くのが面倒なので git commit にフックさせます。
composer install
composer.json に以下を記述
"require-dev": {
"phpstan/phpstan": "\*"
},
"scripts": {
"post-install-cmd": [
"mkdir -p .git/hooks/",
"cp git-pre-commit .git/hooks/pre-commit",
"chmod a+x .git/hooks/pre-commit"
],
}
$ composer install
commit 時にフックさせる
git-pre-commit に以下を記述
PHP\_CODE=$(cat \<\<'EOS'
$output = array();
$return = 0;
exec('git rev-parse --verify HEAD 2\> /dev/null', $output, $return);
$against = $return == 0 ? 'HEAD' : 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; // github repoのハッシュ値
exec("git diff-index --cached --name-only {$against}", $files);
// 対象ファイルの設定
$filenamePattern = '/\.(php)$/';
// 除外ファイルの設定
$ignorePatterns = [
'/^bootstrap\/cache\/.\*(php)$/',
];
$exit\_status = 0;
foreach ($files as $file) {
if (!file\_exists($file)) {
// delete file
continue;
}
if (!preg\_match($filenamePattern, $file)) {
// don't check files that aren't PHP
continue;
}
foreach ($ignorePatterns as $ignoreFilePattern) {
// ignore
if (preg\_match($ignoreFilePattern, $file)) {
continue 2;
}
}
// PHPSTANを実行する
ob\_start();
$stan\_return = [];
exec(sprintf('./vendor/bin/phpstan analyse --no-progress -l max %s', escapeshellarg($file)), $stan\_return, $stan\_error);
$output = ob\_get\_clean();
if ($stan\_error) {
echo PHP\_EOL, "PHPSTAN error", PHP\_EOL;
foreach ($stan\_return as $returnK =\> $returnV) {
echo $returnV, PHP\_EOL;
}
$exit\_status = 1;
continue;
}
}
exit($exit\_status);
EOS
)
php -r "$PHP\_CODE"
php\_status=$?
if test $php\_status -ne 0
then
echo "git pre-commit hook error"
echo "please fix the error and retry commit"
cat \<\<HOGE
if remove from the index:
$ git reset
if edit the file to fix errors and retry commit:
$ edit FILE\_NAME ...
$ git add FILE\_NAME
$ git commit
HOGE
exit $php\_status
fi
コード変更
エラーが出るように変更
\<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\Models\Member;
class MembersController extends Controller
{
/\*\*
\* Display a listing of the resource.
\*
\* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\Viewaaaaaa // 無い型
\*/
public function index()
{
$members = Member::all();
$hoge; // 使用してない変数
return view('members.index', ['members' =\> $members]); // 型がphpdocsの定義と異なる
}
以下省略
git commit
$ git commit -a
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Line MembersController.php
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
17 Return typehint of method App\Http\Controllers\MembersController::index() has invalid type Illuminate\View\Viewaaaaaa.
21 Undefined variable: $hoge
23 Method App\Http\Controllers\MembersController::index() should return Illuminate\Contracts\View\Factory|Illuminate\View\Viewaaaaaa but returns Illuminate\Contracts\View\Factory|Illuminate\View
------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
↑こんな感じで指摘してくれる
[ERROR] Found 3 errors
PHPSTAN error
git pre-commit hook error
please fix the error and retry commit
if remove from the index:
$ git reset
if edit the file to fix errors and retry commit:
$ edit FILE\_NAME ...
$ git add FILE\_NAME
$ git commit
良い感じに指摘してくれます。
PHPMD や PHPlint と被るところは多いと思いますが、色々指摘してくれるので便利です。
ただ、これは指摘だけになりますので、PHP-CS-Fixer と絡めて調整してくれるようにすると良いでしょう。
私は、同じ様に git-pre-commit に全部突っ込んでやってます。
指摘は結構でますが、徐々に意識したコードを書くようになります。
新人・経験者に限らず、入れておくと最初は開発のスピードは落ちるでしょうが、そのうちしっかりとしたコードが書けるようになると思います。
おまけ
PHPStan は Laravel で導入すると、やたらめったらエラーを吐きます。
具体的には、routes/web.php などのファイルで Route クラスってどこにあるの?とかです。
何かいい方法が無いかと調べてみたら、PHPStan の Laravel 用があるようです。
GitHub - larastan/larastan: ⚗️ Adds code analysis to Laravel improving developer productivity and code quality.
⚗️ Adds code analysis to Laravel improving developer productivity and code quality. - larastan/larastan
こいつを使えばエラーが出なくなるので便利です。
Laravel ではこっちを使ってみると良いです。
それでは
hayasaki
主にPHPで業務系のアプリケーションの開発を行っています。