きっかけ
チーム開発をしていて、こんなことがあった。
PhpStormでコードを書いて ⌘S で保存する。動作確認してコミット、プッシュ。数分後にCIが赤くなる。vendor/bin/pint --test で落ちている。差分を見ると、クォートが " のままとか、use の並び順がアルファベット順になってないとか、そういう細かい話。ローカルで vendor/bin/pint をかけ直してまたコミット。
地味に時間を溶かす。
原因はわかっていて、PhpStormの標準フォーマッタとLaravel Pintのルールが一致していないから、⌘S で整形された瞬間に差分が生まれる。だったらPhpStorm側で最初からPintを使わせればいい、というのが今回の話。
やること
PhpStormの「保存時に実行されるフォーマッタ」をPintに差し替える。これだけ。
PhpStorm 2023.1でPintのネイティブサポートが入ったので、2023.1以降なら設定項目がそのまま用意されている。バージョンが古ければ先にアップデートしてほしい。
前提:ホストOSにもPHPが必要
意外と見落としがちだが、PhpStormのPint連携を使うには ホスト(PhpStormが動いているMac/Windows側)にもPHPが入っている必要がある。
開発環境をDockerで完結させているチームだと「PHPはコンテナの中にしかない」ということがよくあるが、それだと動かない。PhpStormはホスト側のPHPバイナリを呼び出してPintを起動する仕組みなので、ホストにもPHPをインストールしておく必要がある。
# Macの場合(Homebrew)
brew install php
バージョンはプロジェクトの composer.json の require.php に合わせる。PHP 8.4が必要なプロジェクトなら brew install php@8.4。
「え、Dockerで統一してるのに?」と思うかもしれないが、PintはDBアクセスも外部通信もしない純粋なフォーマッタなので、ホスト側で実行してもコンテナ内で実行しても結果は同じになる。Pintのバージョンは composer.lock で固定されているので、CIと差分も出ない。
どうしてもコンテナ内のPHPを使いたい場合は、PhpStormのCLI InterpreterでDocker Compose経由を指定する方法もあるが、保存のたびに数秒の遅延が発生するので体感はあまりよくない。
設定
必須は3ステップ、おまけが1ステップ。
1. PhpStormにPintの場所を教える
⌘, で設定を開いて、PHP → Quality Tools → Laravel Pint に進む。
-
Enableにチェック -
Configurationのインタプリタは自動で入るはず -
Path to Laravel Pintがvendor/bin/pintになっていることを確認 -
Validateボタンを押してLaravel Pint detected successfullyが出ればOK -
RulesetはデフォルトのLaravelのまま
[画像: Quality Tools > Laravel Pint]
Validate でエラーが出るときはだいたいPHPインタプリタのパスがずれているので、そこを見直すと通る。
2. インスペクションを有効にする
次の設定の前提になるので、忘れずに。Editor → Inspections を開いて、検索窓に Laravel Pint と入れる。PHP → Quality Tools → Laravel Pint validation にチェック。
Severityは Warning にしておくと、ルール違反のところに波線が出てエディタ上で気づける。
[画像: Inspections > Laravel Pint validation]
3. 保存時にPintを走らせる(本命)
Tools → Actions on Save を開く。
-
Reformat codeにチェック -
Run Laravel Pintにチェック
[画像: Actions on Save]
Run Laravel Pint の項目が出てこなかったら、ほぼ確実にステップ2を飛ばしている。戻って有効化してから再度開くと出てくる。
ここまでで ⌘S すればPintが走るようになる。実質これで完了。
4. (おまけ)⌥⌘L もPintに寄せる
PhpStormには ⌥⌘L(Reformat Code)というショートカットがあって、これはデフォルトだとPhpStorm内蔵のフォーマッタを呼ぶ。つまり「保存時はPint、⌥⌘L は内蔵」という二重状態になる。たまに結果が微妙にズレる。
気になる人は、ステップ1と同じ画面の Use as external formatter にチェックを入れておくと、⌥⌘L もPintに置き換わる。個人的にはこれまで入れている。
[画像: Use as external formatter]
動かしてみる
適当にこんな感じの汚いファイルを用意して保存する。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Enums\Status;
class Example extends Model{
public function test( ){
$x="hello";
return $x ;
}
}
⌘S を押すと、こうなる。
<?php
namespace App\Models;
use App\Enums\Status;
use Illuminate\Database\Eloquent\Model;
class Example extends Model
{
public function test()
{
$x = 'hello';
return $x;
}
}
use がアルファベット順に並び、ダブルクォートがシングルに、{ が次の行に、= 前後のスペース、return の前に空行、引数の余計なスペースも消える。コマンドラインで vendor/bin/pint app/Models/Example.php を実行した結果と一致するはず。
一致してなかったらどこかでステップが抜けているので、設定を見直し。
ちょっとした注意
Run Laravel Pint が出ない問題
先述のとおりインスペクション(ステップ2)を先にやること。ここで詰まる人が多い。
チームで共有したいとき
インスペクションの有効化状態は .idea/inspectionProfiles/Project_Default.xml に書かれる。これをGitに入れるとチームメンバーがプロジェクトを開いたときに同じ設定が効く。ただし .idea 全体をコミットすると個人のUI設定まで入ってしまうので、フォーマッタ関連だけ選んで入れるのが無難。
Bladeはどうするの
PintはPHPファイル専用。Bladeは対象外なのでPrettierのBladeプラグインを別に入れる。これは別で記事にしたい。
brew upgrade php したら急に動かなくなった
これに一度ハマった。PhpStormのCLI Interpreter設定は「PHPバイナリの絶対パス」で記憶されるので、/opt/homebrew/Cellar/php/8.2.5/bin/php のようにバージョン付きのパスを参照していることがある。この状態で brew upgrade php すると古いバージョンがCellarから消えてパスが無効になる。
タチが悪いのは、PhpStormがこのエラーを表示してくれないこと。Actions on Saveの Run Laravel Pint は「バイナリが見つからなかった」場合でも静かにスキップされるので、保存時にPintが走らなくなっているのに気づかない。
症状としては「保存してもクォートが変換されない」「use の並び替えが効かない」など。疑ったら Settings → PHP → CLI Interpreter を開いて、設定されているパスが実在するか確認する。/opt/homebrew/bin/php(シンボリックリンク)を指定しておくと、brew upgradeしても壊れない。
まとめ
⌘S を押してCIが赤くなるループから抜けられるようになったので、個人的には入れてよかった設定。Pintの設定画面を初めて開くと項目が多くて面食らうけど、やることは「Pintを登録する」「インスペクションONにする」「Actions on Saveで選ぶ」の3つだけで、所要時間は実質5分くらい。
もう少し踏み込むなら、プロジェクトに pint.json を置いて独自ルールを足す、という話になる。そこはまた別の機会に。