← Blog一覧へ

Laravel BoostからLaravelの信条を探る

#tech#Laravel#AI

Laravel公式がAIに向けて書いた文章、人間が読んでも面白すぎました。

Laravel Boostとは、公式が提供しているLaravel開発のためのAI補助ツールです。インストールすると、CLAUDE.mdやskills、MCPサーバが一式用意されて、AIがLaravelらしい高品質なコードを書けるようになります。

自分はLaravelを一番使っているのですが、正直、複雑な気持ちになる場面もあります。下位互換を大事にして、柔軟に拡張できるのがLaravelの良さ。でもその柔軟さゆえに、現場ごとに独自の設計・独自ルールで育ってしまう。「構成はLaravelです」と聞いた瞬間、苦虫を噛み潰したような顔をする開発者も見てきました…。気持ちは分かるだけに、心苦しい。

この中身って、公式のLaravel専門家が「Laravelはこう書くべき」を全部言語化したものでは?

普段のドキュメントはユーザーに気を使って書かれていますが、AIに読ませるルールは遠慮がない。つまりここを精読すれば、Laravelが本当に大事にしている信条が読み解けるはず——ということで、rules全20ファイル・約2,000行を読み込んでみました。

探ってみた

先に結論からお見せします。読み終えて感じたのは、Laravelの信条は一貫して「抽象的な美しさ」ではなく「具体的な現場」を向いている、ということでした。

問い 信条
既存コードにどう向き合うか 現場に従う
失敗にどう向き合うか 静かに失敗するくらいなら、うるさく壊れろ
何を信じ、何を疑うか 語彙は信じ、デフォルトは疑う
誰のために書くか 未来の他人のために書く
知識をどう扱うか 憶測せず、見に行く
どこまで作るか 足さない

正直、読む前は「Eloquent使え」みたいな当たり前ルール集を想像していました。全然違いました。以下、特に痺れたところを感想込みで紹介していきます。

Ⅰ. 現場に従う

一番強く感じたのがこれです。しかも単なる「コードスタイルを統一しよう」ではなく、「お前が正しいと思うことは、既存を書き換える理由にならない」という、かなり踏み込んだ主張に読めます。

SKILL.md 「Inconsistency is worse than a suboptimal pattern.」 (一貫性の欠如は、多少劣ったパターンより悪い)

特に面白かったのが validation.md です。

validation.md 「Array syntax is more readable and composes cleanly with Rule:: objects. Prefer it in new code, but check existing Form Requests first and match whatever notation the project already uses.」 (新規コードでは配列記法を推奨する。だがまず既存のForm Requestを見て、プロジェクトが既に使っている記法に合わせろ)

「Aが良い。ただし既存がBならBにしろ」——ベストプラクティスを提示した直後に、それを現場の慣習の下に置いています。既存コードを見て「こう直したい…」とウズウズすることが多い自分に読ませたい一文です。

そして規約は、論理的に導出できなくても従うべきものとされています。

style.md より(Good / Bad の表から抜粋)

対象 規約 Good Bad
コントローラ 単数形 ArticleController ArticlesController
ピボットテーブル 単数形・辞書順 article_user user_article
カラム snake_case・モデル名を含めない meta_title article_meta_title
ルート名 snake_case + ドット users.show_active users.show-active
ビュー kebab-case show-filtered.blade.php showFiltered.blade.php

ルートは複数形なのにコントローラは単数形、ルート名はsnake_caseなのにビューはkebab-case。正直、理屈では導けません。でも、それこそが要点なんだと思います。理屈で擁護できる答えは「もっと良い案」との議論を生みますが、決まりきった答えは議論を生まない——決着済みの答えは、擁護可能な答えに勝つ。議論の余地を消してくれること自体が価値なんだと妙に納得しました。

ちなみに一貫性の守り方も面白くて、mail.md は「呼び出し側で毎回 Mail::queue() を思い出せ」ではなく、Mailableクラス側で一度キューを宣言する方式を推します。人間の注意力ではなく、型と設計で一貫性を強制するという発想。AIは、いま見ているファイルの外にある「プロジェクトの決まり」を覚えていられません。だから「呼び出し側が毎回思い出す設計」ではなく「クラス側で一度宣言する設計」は、AIという書き手に驚くほど噛み合っていると思います。


Ⅱ. 静かに失敗するくらいなら、うるさく壊れろ

Laravelが最も嫌っているのはバグではなく、気づけないバグでした。

ルール群には「silently」という単語が繰り返し出てきます。

eloquent.md「Global scopes silently modify every query on the model, making debugging difficult.」 collections.mdUser::with('roles')->cursor() — eager loading silently ignored.」

例外は出ない。テストは通る。レビューも通る。本番のデータだけが静かに間違っている。……この怖さ、経験者ほど刺さるのではないでしょうか。

だからLaravelは「機械に例外を投げさせろ」と言います。全20ファイル中、コードの書き方ではなくランタイムの挙動そのものを変える唯一のルールがこれでした。

db-performance.md

Model::preventLazyLoading(! app()->isProduction());

「Throws LazyLoadingViolationException when a relationship is accessed without being eager-loaded.」

これ、地味に重い意味を持っていると思っていて、「正しく書け」では不十分だと公式が認めているということな気がします。規律に頼るのをやめて、機械的強制に置き換える。しかも ! app()->isProduction() ——開発では厳格に、本番では寛容に。検知の仕組みが顧客を巻き添えにしないよう、環境で非対称にしてある。この1行の解像度の高さが好きです。

そして、AI時代の観点で全ルール中もっとも引用価値が高いと思ったのがこの一文。

migrations.md 「For intentionally irreversible migrations, leave a clear comment and require a forward fix migration instead of pretending rollback is supported.」 (意図的に不可逆なマイグレーションでは、明確なコメントを残し前進修正を要求せよ。 ロールバックできるふりをするのではなく。)

とりあえず形だけの down() を置くのは「それらしい形を埋める」行為そのもので、公式はそれを「取り消せないと正直に言うより悪い」と断じています。見せかけの成功は、正直な失敗に劣る。耳が痛い人、自分だけではないはずです…。

失敗への向き合い方は他にも徹底していて、migrations.md はDDL(スキーマ変更)とDML(データ操作)を混ぜるなと言います。理由は「きれいだから」ではなく、途中で落ちたときに復旧できないから。さらに非同期系6ファイルでは、約40ルール中15前後が多重実行の防止に費やされていました。キューJobは「あとで動くコード」ではなく、何回動くか分からず、自分自身と同時に動きうるコード。正しさをhappy pathではなくリトライ時の挙動で定義しているのが、いかにも現場を見ている感じがします。


Ⅲ. 語彙は信じ、デフォルトは疑う

「フレームワークを信じろ」とはよく言われますが、Laravelの信条としては半分しか正しくありませんでした。信じてよいのは用意されている道具のほうで、疑うべきはその道具の初期設定。この線引きがはっきりしているのが意外でした。

まず信じる側。ヘルパクラスは「常にこちらを使え」と言い切ります。

style.md 「Laravel provides Str, Arr, Number, and Uri helper classes that are more readable, chainable, and UTF-8 safe than raw PHP functions. Always prefer them.」

ルーティングも同様で、routing.md は “automatically”(Laravelが自動でやってくれる)を4回、すべて称賛として使っています。

ところが同じルール群が、今度はLaravel自身のデフォルト値を名指しで攻撃するんです。

http-client.md「The default timeout is 30 seconds — too long for most API calls.」 http-client.md「The HTTP Client does not throw on 4xx/5xx by default.」 queue-jobs.md(コメント)「// Default: retries immediately, overwhelming the API」

公式が自分のデフォルトを「too long」と切り捨てるの、潔くて好きですw。要するにLaravelのデフォルトはローカル開発の快適さに最適化されていて、これらのルールはすべてその本番向け差分なんですよね。整理するとこうなります。

Laravelが用意した道具は信じよ。Laravelが決めた初期値は疑え。

もうひとつ、blade-views.md の「(hidden coupling)」という表現が刺さりました。

blade-views.md@include shares all parent variables implicitly (hidden coupling). Components have explicit props, attribute bags, and slots.」

@include は親の変数を暗黙で全部引き継ぎます。ここで一見矛盾が生じます。同じ「暗黙」でも、ルーティングの自動解決は褒められ、Bladeの変数共有は断罪される。

違いは「誰が決めた暗黙か」でしょう。ルートモデルバインディングはLaravelの仕様なので、ドキュメントを引けば誰でも辿れます。一方 @include の変数共有は、そのプロジェクトを書いた人しか知らない。フレームワークが所有する暗黙は「契約」だけれど、自分が書いた暗黙はただの「隠れた結合」というわけです。

さらに advanced-queries.md では、whereHas() が行ごとに再実行される相関 EXISTS サブクエリを吐くこと、複合インデックスがなければDBが filesort に落ちることまで、生成されるSQLと実行計画で正当化が行われています。ORMを使う以上、吐かれるSQLに責任を持て——ORMは魔法ではなくSQLジェネレータだという立場が徹底していて、ここは読んでいて一番勉強になったパートでした。


Ⅳ. 未来の他人のために書く

Laravelは「今動くか」ではなく、「あとで人が辿れるか」でしばしば決着をつけます。

たとえば error-handling.mdShouldntReport インターフェースを勧める理由は、挙動が優れているからではなく「More discoverable than listing classes in dontReport()」——例外クラス自身を見たときに気づけるから。eloquent.md がテーブル名のハードコードを嫌う理由も「正しさ」ですらなく、将来grepできなくなるからです。設計判断の根拠が「未来の検索性」なの、地味ですがすごく実務的で好きです。

コメントについての立場もはっきりしていました。

style.md 「Code should be readable on its own. Use descriptive method and variable names instead of comments.」

注目すべきは修正の方向です。

// Incorrect
// Check if there are any joins
if (count((array) $builder->getQuery()->joins) > 0)

// Correct
if ($this->hasJoins())

コメントを消すのではなく、コメントを名前にしたメソッドを抽出している。コメントは機能ではなく、抽象が足りないことの症状として扱われているわけです。

そして個人的に一番意外だったのがテストです。testing.md には「テストを書け」という指示が一つもありません。カバレッジもTDDも出てこない。テストは存在する前提で、書き方だけを規定している。しかも評価軸が「壊れたときに何を教えてくれるか」(fails with clearer messages)。テストが一級市民であることを命令ではなく扱いで示している——アプリコードと同じ「名前を付けろ・雑にするな」という水準を課している——のが、なんというか、粋だなと思いました。


Ⅴ. 憶測せず、見に行く

Laravel BoostがMCPサーバ(search-docs / database-schema / last-error など)を同梱していること自体が、この信条の表明だと思います。

CLAUDE.md「Always use search-docs before making code changes. Do not skip this step.」 CLAUDE.md「Use database-schema to inspect table structure before writing migrations or models.」

面白いのは、ルールファイル自身が自分は不完全であると明言しているところ。style.md は「Use search-docs for the full list of available methods」と、記憶より参照を指示しています。AIの弱点(学習時点の知識で憶測する)を正確に踏まえた設計で、これは自分がCLAUDE.mdを書くときにも真似したいポイントでした。

もうひとつ痺れたのが、error-handling.md でLaravelが珍しく正解を出さないことです。例外処理を例外クラス側に置くか、bootstrap/app.php に集約するか——両案の長所を誠実に併記した上で、こう言います。

「There are two valid approaches — choose one and apply it consistently across the project.」 「Check the existing codebase and follow whichever pattern is already established.」

命名やAPI選択にはあれほど規範的なのに、アーキテクチャの分岐点では意図的に規範を降ろす。含意はこうでしょう——規約に判断力を使うな。アーキテクチャに確信を使うな。

ちなみに「見に行けない現実」への警告も現場感がありました。env('API_KEY') の直接呼び出しは正しく見えて、ローカルのテストも通り、php artisan config:cache が走った瞬間にだけ壊れる。コードベースのどこにも「デプロイ時に何が走るか」は書かれていない。これは知識の問題ではなくコンテキストの問題なんですよね。


Ⅵ. 足さない

SKILL.md「Avoid speculative abstractions.」 CLAUDE.md「don’t create new base folders without approval」 CLAUDE.md「You must only create documentation files if explicitly requested by the user.」 config.md「Do not introduce language files purely for English-only apps — simple string literals are fine there.」

config.md の最後の一文が良くて、これは「抽象しなくてよい」という明示的な許可なんです。ベストプラクティスは、必要になるまで導入しない。AIが放っておくと律儀にREADMEや抽象レイヤーを量産しがちなことを考えると、この「足すな」の連打には日頃の恨みすら感じますw

簡潔さには数値まで置かれていました。

routing.md「Aim for under 10 lines per method. Extract business logic to action or service classes.」

全20ファイルで唯一の数値基準です。

ただし「安全」だけは重ねてよい

面白いのは、security.md だけがこの信条から明確に外れることです。

security.md「Every model must define $fillable (whitelist) or $guarded (blacklist).」 security.md「Use policies or gates in controllers. Never skip authorization.」 security.md「Validate extension, MIME type, and size. … Never trust client-provided filenames.」

DBカラムを暗号化した上で $hidden にも入れる。拡張子もMIMEもサイズも検証する。冗長性が正しさとして扱われる——DRYや簡潔さと真っ向から対立してでも、です。

そして気づいたのが、security.md のIncorrect例はどれも「楽な方のコード」なんです。$guarded = [] は生成コードをすぐ動かしてくれるし、認可の1行は無くても他が完璧に見える。つまり——

セキュリティにおける脅威モデルは、攻撃者ではなく「便利さ」である。

これは今回の精読で得た、一番持ち帰りたい視点でした。


信条は絶対ではない——文脈で反転する

最後に、精読して最も驚いた点を。ここまでの信条は、特定の文脈で反転します。

信条 反転する場所 何が起きるか
最小変更 migrations.md デプロイ済みマイグレーションでは、最小差分(1行追加)が禁止。新ファイル作成という大きい差分が正解
簡潔さ advanced-queries.md with('logins') の1行より、addSelect + withCasts + スコープの8行が正解
フレームワークを信じる 全体 グローバルスコープ・whereHas()cursor()・JOINは一級機能だが「避けろ」

そして公式自身が、ルールより判断が上位にあると認めている箇所があります。

advanced-queries.md(見出し) 「Sometimes Two Simple Queries Beat One Complex Query」

db-performance.md が193行かけて刷り込む「クエリは少ないほど良い」を、別のファイルが条件付きで明示的に否定している。一見矛盾しているように見えて、むしろこれこそが結論なんだと思います。

規約には従え。アーキテクチャは現場に聞け。パフォーマンスは測って判断しろ。


まとめ

Laravelの “Convention over Configuration” は、単に設定を減らす思想ではありませんでした。「決めごとに判断力を浪費するな。判断力は、現場でしか決められないことに使え」という、リソース配分の思想として読むほうが正確だと思います。

冒頭の話に戻ると、Laravelが現場ごとに独自ルール化してしまう問題も、この信条群がAI経由でコードに染み込んでいけば、少しずつ解消に向かうんじゃないかと期待しています。


参考

本記事のソースは、すべて php artisan boost:install で生成されます。

ファイル 内容
CLAUDE.md / AGENTS.md 合成後ガイドライン
.claude/skills/laravel-best-practices/SKILL.md Rule Index と How to Apply
.claude/skills/laravel-best-practices/rules/*.md 領域別ルール全20本(約2,000行)