『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"
一見すると便利そうですが、これをやると…
- カオス化の始まり:
composer.jsonにはコメントが書けないため、設定がごちゃごちゃしてきます。 - 誰も使わなくなる: 「なんか分かりにくいな…」と感じはじめて、使わなくなり、メンテされなくなります。
- 野良エイリアスの乱立:
- Aさん:
alias csfix="docker compose exec php vendor/bin/php-cs-fixer fix" - Bさん: 手元に自分専用の隠し Makefile を置く
- Cさん: ローカルに謎の
php-cs-fix.shを作る
- Aさん:
- 負の伝承: 新規参加者が入ってきたとき、たまたま聞いた人のローカル環境のやり方を伝承してしまいます。
2. 解決策:3レイヤー構造
このカオスをきれいに整理するため、役割ごとに担当ファイルをきっちり分けた「3レイヤー構造」を採用しました。
| レイヤー | 実行場所 | 担当ファイル | 役割と特徴 |
|---|---|---|---|
| 外側(Bridge) | ホストOS | Makefile | ホストから Docker の中へ安全に命令を届ける唯一の窓口。make setup だけで誰でも一発復旧! |
| 内側(PHP/App) | Dockerコンテナ内 | composer.json (scripts) | 純粋な PHP 世界のツール集。 Dockerの存在は知らず、ポータブルに動く。 |
| 内側(Host/Meta) | ホストOS | package.json | Node/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 Testtest:golden-master-update- Golden Master のデータ更新
② package.json (ホストOS / Node.js)
Dockerに入らず、ホストOS(Ubuntuなど)の pnpm で動かします。MarkdownやYAML、フロントエンド関連の軽量なリントはホスト側で完結させます。
format:fix-Prettierでフォーマットlint-ESLintts-check- TypeScript による型チェック(JSDocを通した緩やかな型安全性)
③ Makefile (ホストからDockerを叩くブリッジ)
「Dockerの外から中へコマンドを投げる」という、やや冗長になりがちな操作を隠蔽します。
make php-format-fixmake php-lintmake php-lint-baselinemake php-testmake php-test-golden-mastermake php-test-golden-master-updatemake 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)を組み合わせて、コマンドの迷子をなくし、開発者体験を向上させましょう。
参考コード
- Makefile https://github.com/ninton/smartybook/blob/main/Makefile
- composer.json https://github.com/ninton/smartybook/blob/main/composer.json
- package.json https://github.com/ninton/smartybook/blob/main/package.json
