レガシーPHPリファクタ 21:Makefile と composer.json の scripts の整備

『Smarty動的Webサイト構築入門』のサンプルコードを、現代の基準(PHP 8.5 & Smarty 5)でリファクタリングしていくこの連載。

今回は、リファクタリングを進めるうえで避けて通れない「開発タスクの実行環境(コマンド管理)」のお話です。

レガシーなPHPプロジェクトを触っていると、こんなプチストレスに悩まされませんか?

  • 「あれ、このコードフォーマットするコマンド、Dockerの外だっけ、中だっけ?」
  • 「毎回 docker compose exec php ... って打つのが長すぎてタイポする…」
  • 「気づいたら人によってバラバラのエイリアスが乱立している!」

今回は、こうした「コマンド迷子」を綺麗に解決し、毎日のコミット前のルーティンをストレスフリーにする「3レイヤー構造のタスク管理」についてご紹介します!


1. なぜ composer.json に Docker コマンドを書いてはいけないのか

PHPのプロジェクトでは、ホストOS上で複数のPHPバージョンを切り替えるのが難しいため、「Dockerコンテナの中に入って各種コマンドを実行する」のがデファクトスタンダードです。

そこで、うっかりやってしまいがちなのが composer.json の scripts に Docker経由のコマンドを書いてしまうこと。

"docker:php-cs-fix": "docker compose run --rm php-web composer run-script php-cs-fix"

一見すると便利そうですが、これをやると…

  1. カオス化の始まり: composer.json にはコメントが書けないため、設定がごちゃごちゃしてきます。
  2. 誰も使わなくなる: 「なんか分かりにくいな…」と感じはじめて、使わなくなり、メンテされなくなります。
  3. 野良エイリアスの乱立:
    • Aさん: alias csfix="docker compose exec php vendor/bin/php-cs-fixer fix"
    • Bさん: 手元に自分専用の隠し Makefile を置く
    • Cさん: ローカルに謎の php-cs-fix.sh を作る
  4. 負の伝承: 新規参加者が入ってきたとき、たまたま聞いた人のローカル環境のやり方を伝承してしまいます。

2. 解決策:3レイヤー構造

このカオスをきれいに整理するため、役割ごとに担当ファイルをきっちり分けた「3レイヤー構造」を採用しました。

レイヤー実行場所担当ファイル役割と特徴
外側(Bridge)ホストOSMakefileホストから Docker の中へ安全に命令を届ける唯一の窓口。

make setup だけで誰でも一発復旧!
内側(PHP/App)Dockerコンテナ内composer.json (scripts)純粋な PHP 世界のツール集。

Dockerの存在は知らず、ポータブルに動く。
内側(Host/Meta)ホストOSpackage.jsonNode/pnpm ツール群。

Dockerに入らず、PrettierやESLint等を回す。

それぞれのファイルの役割をもう少し詳しく見てみましょう。

① composer.json (Docker内 / PHP)

アプリケーションのランタイム(PHP 8.5など)と完全に一致した環境で動きます。PHPStan、php-cs-fixer、Pestなどのツールはここで一元管理し、バージョンのズレを防ぎます。

  • format:fix - php-cs-fixer でコードフォーマット
  • lint - PHPStan で静的解析
  • lint:baseline - PHPStan の baseline 更新
  • smarty-lint - Smartyの構文チェック
  • test - Pest による単体テスト
  • test:golden-master - クロールベースの Golden Master Test
  • test:golden-master-update - Golden Master のデータ更新

② package.json (ホストOS / Node.js)

Dockerに入らず、ホストOS(Ubuntuなど)の pnpm で動かします。MarkdownやYAML、フロントエンド関連の軽量なリントはホスト側で完結させます。

  • format:fix - Prettier でフォーマット
  • lint - ESLint
  • ts-check - TypeScript による型チェック(JSDocを通した緩やかな型安全性)

③ Makefile (ホストからDockerを叩くブリッジ)

「Dockerの外から中へコマンドを投げる」という、やや冗長になりがちな操作を隠蔽します。

  • make php-format-fix
  • make php-lint
  • make php-lint-baseline
  • make php-test
  • make php-test-golden-master
  • make php-test-golden-master-update
  • make setup - git clone直後やpull直後のセットアップまとめ

3. 「長いDockerコマンド」をMakefileで隠蔽するストレスフリーさ

毎回 docker compose exec php vendor/bin/pest のように打つのは、タイポも増えるし心理的なハードルになります。

Makefileでラップしてあげれば、開発者はDockerの存在を忘れて、まるで自分のローカルOSにPHPが入っているかのようなネイティブ感覚でタスクを叩けます。

特に、git clone 直後や git pull 直後に make setup を叩くだけで一撃で環境が整う安心感は、チーム開発はもちろん、未来の自分にとっても最高の投資になります。


4. 毎日の開発・コミット前のルーティン

実際のターミナルでの作業は、こんな風にとてもシンプルになります。

# 1. PHP や Smarty をコミットする前
make php-format-fix && make php-lint && make php-test && make php-php-test-golden-master

# 2. JS、MD、YAML などの PHP 以外をコミットする前
pnpm run format:fix && pnpm run lint && pnpm run ts-check

# 3. Golden Master を更新したいとき
make php-php-test-golden-master-update

# 4. PHPStan の baseline を更新したいとき
make php-lint-baseline

# 5. git pull 直後
make setup

また、AIにコード修正を指示するときの締めくくりとしても、これらのコマンドを指定しておけば安心です。

AIへの指示の最後に:

次の検証コマンドを実行してください
`make php-format-fix`
`make php-lint`
`make php-test`
`make php-test-golden-master`
`pnpm run format:fix`
`pnpm run lint`
`pnpm run ts-check`
Code language: JavaScript (javascript)

単なる単体テスト(Pest)だけでなく、レガシー改修で一番怖いデグレを防ぐ「クロールベースの Golden Master Test」や「PHPStanのbaseline更新」が、日常のワークフローにスムーズに組み込まれているのがポイントです。


まとめ

コードのリファクタリングだけでなく、それを支える「開発ワークフローの整備」は同じくらい重要です。

適切なタスクランナー(Makefile × composer.json × package.json)を組み合わせて、コマンドの迷子をなくし、開発者体験を向上させましょう。

参考コード

タイトルとURLをコピーしました