
Laravel
イベント

マガジン
技術ブログ
はじめに こんにちは、リテールハブ開発部でバックエンドエンジニアをしているホシと申します。 現在、Laravel などを利用しながら小売アプリ開発に取り組んでいます。 先日、サービスのリリースに伴い、旧サービスの外部システムから当社のMySQL DBへユーザーデータ移行を行う機会がありました。 ただ今回、今まで行ったデータ移行と大きく違うのは、ユーザーの個人情報を含んだデータ移行でした。 データ移行自体はこれまでも経験していましたが、個人情報を含む移行は前提が異なり、多くの学びと反省点がありました。 そこで本記事では以下の点についてお話できればと思います。 実データを自由に扱えない状況での事前準備の進め方 リハーサルの重要性と、実施できる場合の考え方 今回採用した移行方式と「変換できたのに正しく入っていない」問題と確認点 移行当日に意識しておくべき判断と心構え 次回のデータ移行に向けた改善点 それぞれの中で経験したことや反省点を記載しながら、今後に向けた改善点などを記載しています。 また、個別の移行内容というよりは、データ移行を進める際の準備・検証・判断の考え方に焦点を当てています。 1. 実データを自由に扱えない状況での事前準備の進め方 個人情報を含むデータは「自由に触れない」 個人情報が含まれる場合の制約 開発環境・検証環境に簡単に持ち込めない ログ出力、スクリーンショット、共有方法にも制限がある データ配置・保管場所にも慎重な判断が必要 事前確認が十分にできない 「本番で初めて見るデータ」が発生しがち など通常とは異なる制約がある中で行う必要がありました。 この部分をもっと考慮した上で、事前準備が必要であったところは大きな反省点でした。 「できないから仕方ない」で済ませると危険 事前にできることはできる限りやり、仕様書・IF定義だけで満足しないことが大事です。 とはいえ対応できる範囲も限界はあるので以下の点を特に注意できればと思っています。 NULL / 空文字 / 不正値の扱いは各項目でどうなっているのかを明確にする。 桁数・文字種・フォーマットのばらつきがあることを前提とした考慮をする。 仕様上はOKでも、実データでは違う可能性を考える。 (ここは正直難しいですが、データパターンを確認し、できる限り考慮したいです。) あるあるの話ですが、通常は仕様に基づいて対応するのが当たり前ですが、 こういった大量データになるとおかしなデータはほぼ混ざっているのが逆に普通かと思っています。 2. リハーサルの重要性と、実施できる場合の考え方 今回は事前にリハーサルが実施できる状況でした。 しかし、以下の点でしか検証を行えていませんでした。 データ移行手順が問題ないこと(スムーズに移行作業が完了できる) 個人情報データの取り扱いに問題がないこと データ変換がエラーなく行われ、正常にDBへ投入できること(想定通りのフォーマットであること) 実際に移行したデータを使用して簡単な動作確認を実施し問題ないこと 上記はどれもリハーサルで行う必要な項目で、どれも大事なのですが、 ただ、本番データを想定した観点としては以下の点でもっと時間をかけて行うべきでした。 DBに入った内容に想定していないデータが入っていないか データパターンを各項目で洗い出し、システム上問題ない値であること 想定していないパターンの場合、どう対処するかを事前に明確にすること しかし、これも個人情報のデータとなると、あまり時間をかけてのリハーサルや ローカルに保存して後ほど詳細に確認もしにくいのもあり、簡単な確認で済ませてしまっていました。 元データを最大限に利用する 一番確実なのはやはり元データを使用できることです。 当日のデータ移行の検証という意味では、これを利用した検証が一番確実だと思います。 リハーサル当日だけで出来ない部分は、別日に詳細にできればと良いと思います。 しかし、今回のような個人情報データは自由に扱えないことを理由にうまく利用できていなかったのも反省点です。 いかにここでそのファイルを活用したダミーデータを作れるかも非常に有効だったのではと思っています。 3. 今回採用した移行方式と「変換できたのに正しく入っていない」問題と確認点 どうやって移行を行おうとしたか 今回は以下の方法で行いました。 移行元データ ↓ phpでデータを読み込み、MySQLのLoadData用TSVファイルにコンバートするコードを作成 ↓ Load DataでTSVデータをDBへ投入 ↓ データ移行完了 特別な処理は特になく、シンプルな変換処理でした。 「変換できたのに正しく入っていない」問題と確認点 コンバートまでは特に問題なく変換できて、件数・エラーチェックは行えていましたが、 以下の点が見落としポイントでした。 データ投入できていて、かつ全件「自動変換」など発生なく投入できているか? Load時にWarningなどが発生していないか?(投入はできていても実は正常に入っていないケースがある) カラム定義上は問題なく入っているが、値が想定していないものではないか? Load Data はデータ投入時に非常に便利ですが、上記の点をしっかりと考慮した上で使用しないとデータ移行時の確認内容としては不十分になってしまいます。 特に日付はNULLの場合と「0000-00-00」で入る場合で全く挙動が異なります。 MySQLでは「0000-00-00」はNULLではなく「値」として扱われます。 そのためアプリケーション側では未設定ではなく異常値として存在してしまうことになり、 日付計算・バリデーション・ORM変換で後から問題を引き起こす可能性があるので特に注意が必要です。 今回の移行処理の責務を分離して考える 本来は以下のようにそれぞれのフェーズの責務を明確にして、対応をしていく必要がありました。 フェーズ 役割 保証すること 保証できないこと コンバーター 生データをLoad Data用形式へ変換 TSV構造・文字コード・基本的な値変換 DBがどう解釈するか、業務的な正しさ Load Data DBへ高速に一括投入 指定件数の取り込み、物理的な格納 型変換の影響、暗黙変換、Warningの発生 DB格納後の確認 実データの妥当性検証 業務的に正しい値であることの確認 この確認を行わないと移行成功とは言えない 特に今回は、Load Data の部分とDB格納後の確認が混在した確認になっていたと反省しています。 実際のデータパターンの検証例 パターンは膨大にあるようで、実はシンプルなものをいくつか用意しておくだけでも違うと思っています。 -- 不正日付確認 SELECT COUNT (*) FROM users WHERE birthday = ' 0000-00-00 ' ; -- NULL発生率確認 SELECT COUNT (*), SUM (email IS NULL ) FROM users; -- 想定外形式確認(都道府県以外のパターン確認) SELECT prefecture, COUNT (*) FROM users GROUP BY prefecture; AIを活用したパターン洗い出し・事前テストの試み 今回、AIをうまく使いこなせていなかった点も反省点だったと思っています。 まさにAIをうまく活用できる点として、 前述したデータパターンを様々な観点で出すことができる 個人情報部分は適当なパターンデータに変換して検証することもできる 当時は本番データをそのまま使用できないことで、ちょっとしたサンプルデータ、パターンデータで行い、 十分な事前検証も不足していました。 4. 移行当日に意識しておくべき判断と心構え 今までいくつか事前準備と慎重な検証が必要と記載をしていますが、 当日は必ず想定外が起きると思って計画を立てた方が良いかと思っています。 特に膨大なデータや内容が多いほど顕著になるかと思います。 以下の点に注意して当日は望めるようにしておきたいです。 1つ1つの作業完了条件を明確にしておくこと。 ロジックや仕様変更をその場でする修正は原則しないこと。 移行を中止、延期する、または後日対応でOKかなどの判断が当日できる人がいること。 移行がもし出来ない場合のリカバリ方法があること。 また、時間も想定しているよりも掛かってしまうことが多いと思います。 なるべく余裕をもった計画にしたいです。 今回は投入データの件数確認でさえ、すぐに終わるつもりが件数の正解を事前に用意していなかったため、 非常に大きく時間をかけてしまったのも今回の反省点でした。(完了条件が明確になっていない) 5. 次回のデータ移行に向けた改善点 今回の経験から以下の点を意識し改善できるようにしていきたいです。 一連の手順、動作確認は事前リハーサルでできる限り行うこと。 本番当日に向けた事前準備はしっかり時間を確保して対応する。(当日は必ず何か起きる前提) 当日の作業の完了基準の明確化(データ件数、エラー有無、動作確認など) Load Dataなどデータ投入後の部分が一番大事かつ明確にする部分であること。 仕様通りに作成しても、不正データは必ずある前提で行い、それらも考慮すること。 個人情報を扱うデータの場合は、同等のダミーデータを用意できると検証時に非常に有効。 検証パターン、データ生成などはAIも活用し、検証精度やコスト減に役立てる。 6. まとめ 通常、データ移行は当日一度きりの作業で、 同じ内容で再度実施するケースは少なく、個別のノウハウは蓄積しにくいところもありますが、 共通の考え方、対応として、 事前準備の重要性 検証設計の明確化 当日の判断基準 何かあった時のリカバリ方法 これらを意識することで、当日の障害確率は下げられると思っています。 改めて今回を通じて、データ移行は技術作業というより、検証設計と判断設計の仕事だったと感じています。 正直、完璧に準備をして全てスムーズに完了させることはなかなか難しいところですが、 もし今後データ移行などの作業をする際に本記事が少しでも参考になれば幸いです。 最後までお読みいただきありがとうございました。
はじめに こんにちは、リテールハブ開発部の杉森です。 近年、AIを活用した開発ツールが急速に普及しています。私たちのチームでも積極的にAIツールを導入し、要件定義でのユーザーストーリー作成、設計ドキュメントの生成、コードの自動補完、テストコードの生成など、各開発フェーズの作業効率化を図ってきました。 しかし、個々の作業は確かに早くなっているのに、プロダクト開発フロー全体を見ると期待したほどの生産性向上を実感できないという課題に直面しました。 本記事では、この課題に対するアプローチとして導入を検討しているAI-DLC(AI-Driven Development Lifecycle)について紹介します。 AI-DLCとは AI-DLCは、AWSが提唱するAIネイティブな開発方法論です。方法論のホワイトペーパーで理論的な枠組みが定義されており、これを実装するためのワークフローがaidlc-workflowsとしてGitHub上で公開されています。 AWSの公式ブログでは、現在のAI活用における2つのアンチパターンが指摘されています。 AI-Assisted: 人間が設計を主導し、AIはコード補完など狭い範囲の支援にとどまる。生産性向上は限定的で、AIの能力を十分に引き出せない AI-Managed: 複雑な問題をAIに丸投げし、自律的にすべてを解決することを期待する。出発点が曖昧なためAIが多くの仮定を立て、プロトタイプ以外ではほぼ機能しない AI-DLCは、これらのアンチパターンに対するアプローチとして設計されています。AIが作業計画の作成やタスク分解を主導し、人間がその内容を検証・承認し、AIが承認された計画に基づいて実行するというサイクルで、開発ライフサイクル全体を進めます。 AI駆動開発ライフサイクル(AWS公式ブログ) aidlc-workflows(GitHub) 従来の開発手法との違い AI-DLCは、既存の開発手法にAIを後付けするのではなく、AIを前提とした開発プロセスをゼロから設計しています。ホワイトペーパーでは、以下の設計思想が示されています。 AIが会話を主導する: 従来は人間がAIに指示を出していたが、AI-DLCではAIがタスク分解や提案を行い、人間は承認・判断に集中する Intent / Unit / Bolt: ビジネス目標(Intent)を作業単位(Unit)に分解し、数時間〜数日の短いサイクル(Bolt)で実装を回す。ScrumのSprintに近いが、サイクルが短い 各ステップで人間がチェックする: AIの出力を段階ごとに検証し、誤りを早期に検出する。ホワイトペーパーでは「損失関数のように機能する」と表現されている 設計技法を方法論に組み込む: ScrumやKanbanがチームに委ねていたDDD等の設計技法を、方法論の一部として標準化する aidlc-workflowsの設計原則 aidlc-workflowsは、上記の設計思想を実装するにあたり、以下の5つの設計原則に基づいています。 原則 説明 No Duplication 設定やルールを一箇所で管理し、重複を排除する Methodology First 特定のツールに縛られず、方法論そのものを軸にする Reproducible ルールを明文化し、使うAIモデルが変わっても結果がぶれないようにする Agnostic IDE・エージェント・モデルを問わず動作する Human in the Loop 重要な判断には必ず人間の承認を挟む 3フェーズ構成 AI-DLCは、以下の3つのフェーズで構成されています。 INCEPTION PHASE: WHATとWHYの決定 CONSTRUCTION PHASE: HOWの実装 OPERATIONS PHASE: デプロイと監視(aidlc-workflows上は未実装) INCEPTION PHASE 「何を作るか(WHAT)」「なぜ作るか(WHY)」を決定するフェーズです。方法論のホワイトペーパーでは「Mob Elaboration」というプラクティスとして定義されており、共有画面を使ってチーム全体でAIの質問と提案を検証します。AIがビジネス意図(Intent)を明確化する質問を投げかけ、ユーザーストーリー、非機能要件、リスク記述を生成し、凝集度の高い作業単位(Unit)へ分割します。 aidlc-workflowsでは、このフェーズが以下のステージに細分化されています。 ステージ 説明 Workspace Detection プロジェクトの状態を分析(新規/既存の判定) Reverse Engineering 既存コードベースの理解(Brownfieldの場合) Requirements Analysis 要件の収集と整理 User Stories ユーザーストーリーの作成 Workflow Planning 実行計画の策定 Application Design アプリケーション設計 Units Generation 作業単位への分割 CONSTRUCTION PHASE 「どう作るか(HOW)」を決定し、実際にコードを生成するフェーズです。方法論のホワイトペーパーでは、Domain Design(ビジネスロジックのドメインモデリング)→ Logical Design(非機能要件を含むアーキテクチャ設計)→ Code & Unit Tests(コードとテストの生成)→ Deployment Units(デプロイ可能な成果物の構築)という流れで進みます。「Mob Construction」でチームがリアルタイムで技術的決定とアーキテクチャの選択を行います。 aidlc-workflowsでは、このフェーズが以下のステージに細分化されています。 ステージ 説明 Functional Design 機能設計(ユニットごと) NFR Requirements/Design 非機能要件の設計 Infrastructure Design インフラ設計 Code Generation コード生成 Build and Test ビルドとテスト OPERATIONS PHASE デプロイと監視を担当するフェーズです。方法論としては定義されていますが、aidlc-workflowsには含まれておらず、将来的にワークフローが追加される予定です。 対応プラットフォーム 公式では以下のプラットフォームがサポートされています。 Kiro CLI Amazon Q Developer IDE plugin Kiro IDE(Coming Soon) 試してみる 導入の背景 私たちのチームの課題は、まさにAI-Assistedパターンに該当します。AIを個々の作業の効率化には活用できているものの、生産性向上は限定的にとどまっていました。 私たちのチームでは、Kiro CLIをすぐに使える環境ではなかったため、Claude Code向けにカスタマイズして使用しました。AI-DLCはツールに依存しない設計を謳っているため、ルールファイルを調整すれば他のAIツールでも問題なく適用できると考えています。 Claude Code向けのカスタマイズ 以下のようにClaude Code向けにカスタマイズしました。 1. カスタムコマンド(スキル)の作成 .claude/commands/aidlc.md にワークフロー定義を配置し、 /aidlc コマンドで起動できるようにしました。 .claude/ ├── commands/ │ ├── aidlc.md # メインワークフロー │ ├── aidlc-pr.md # PR作成用 │ └── aidlc-archive.md # アーカイブ用 └── aidlc-rule-details/ ├── common/ # 共通ルール ├── inception/ # INCEPTIONフェーズ ├── construction/ # CONSTRUCTIONフェーズ └── operations/ # OPERATIONSフェーズ 2. ルールファイルの分割 各ステージの詳細指示を .claude/aidlc-rule-details/ 以下に分割配置しています。これにより、AIが必要なタイミングで必要なルールのみを読み込み、コンテキストを効率的に使用できます。 クーポン機能を題材にした検証 AI-DLCの有効性を検証するため、小売向けアプリのクーポン機能開発を題材に検証を実施しました。 検証概要 対象システム: Flutter + Laravel + Vue.js + Goで構成されたマルチプラットフォームアプリ 題材: ポイント後付けクーポンと即時値引きクーポンの2種類 検証範囲: モバイルアプリ、管理画面、バックエンドAPI、バッチ処理 チーム構成: PdM1人+エンジニア2人 検証の進め方 「クーポン機能を追加したい」というビジネス意図(Intent)を起点に、AI-DLCのフェーズに沿って進めました。 INCEPTION PHASE(3人で実施): AIが要件を深掘りする質問を投げかけ、ユーザーストーリーや非機能要件を生成。PdMとエンジニアがその内容を検証・修正し、作業単位(Unit)に分割 CONSTRUCTION PHASE(1人で実施): Unitごとにドメイン設計、コード生成、テスト生成を実施。各ステージでAIの出力を確認し、承認・修正を繰り返した 今回は検証目的だったこともあり、各フェーズ半日ずつの計1日で実際に動くものまで作成できました。Inceptionフェーズの要件・設計をより作り込み、Constructionフェーズではガードレールの整備やAIが自律的に改善できる体制を組むことで、さらに短縮できる余地があると感じています。 実際の様子 AIからの深掘り質問(Inceptionフェーズ) Requirements Analysisでは、AIが要件の曖昧な部分を選択肢付きで質問してきます。以下はその一例です。 AI : クーポン利用状態の管理について確認させてください。ユーザーがクーポンを「利用」した後の状態管理はどうなりますか? A) 1回利用したら即座に使用済みになる(再利用不可) B) 有効期限内であれば何度でも利用可能 C) クーポンごとに利用回数を設定可能(1回、3回、無制限など) AI : クーポンの種類と適用範囲について確認させてください。 A) 全ての種類が両方のクーポンタイプで使用可能 B) クーポンタイプごとに使用可能な種類が決まっている このように、AIが仕様の選択肢を提示し、人間が判断するというサイクルでRequirements Analysisが進みます。初回の質問10問、追加の深掘り質問6問を経て、要件定義ドキュメントが生成されました。 人間による設計修正(Inceptionフェーズ) Application Designでは、AIが設計の選択肢を提示し、人間が判断するケースがありました。 人間 : アクティブユーザーではないユーザーにもレコードが作成されてしまいませんか? AI : 2つの選択肢があります。 A) クーポン公開時に全ユーザー分のuser_couponsレコードを作成 B) クーポン利用開始時にのみuser_couponsレコードを作成 人間 : B 生成されたユーザーストーリー(Inceptionフェーズ) User Storiesでは、管理者向け6件、会員ユーザー向け6件、システム向け1件の計13件が生成されました。以下はその一部です。 US-01: クーポン新規作成 As a 管理者 I want to 管理画面から新しいクーポンを作成したい So that 会員ユーザーに対してキャンペーンを提供できる Acceptance Criteria: クーポンタイプ(ポイント後付け/即時値引き)を選択できる クーポン名と説明文を入力できる 有効期限(開始日・終了日)を設定できる 対象店舗を選択できる 生成されたコード(Constructionフェーズ) Constructionフェーズでは、Unitごとにドメイン設計 → コード生成 → テスト生成が進みます。最終的に以下の規模のコードが生成されました。 Unit 対象 生成ファイル数 主な成果物 Backend Laravel 51ファイル Enum, Model, Migration, Service, Controller, Test Dashboard Vue.js 16ファイル Composable, Component, Schema, Page Mobile Flutter 38ファイル Entity, Repository, Provider, Widget, Page わかったこと / 今後の展望 良いと感じた点 実際にAI-DLCを触ってみて、以下の点が良いと感じました。 Human in the Loopの実現: AIが実行し、人間が監視するという関係性が明確。各ステージで人間の承認が必要なため、重要な意思決定は人間がコントロールできる コンテキストの保存と再開: aidlc-state.md でプロジェクトの状態を追跡しているため、セッションが途切れても前回の続きから再開できる ドキュメント化による追跡可能性: audit.md にすべてのやり取りが記録されるため、なぜその決定をしたのかを後から追跡できる 適応的なワークフロー: プロジェクトの複雑さに応じて、実行するステージが自動的に調整される 試した上で見つかった課題 Inception前の準備の必要性 今回「クーポン機能を追加したい」というリクエストからInceptionを開始しましたが、背景知識や「なぜこの機能が必要なのか」がアウトプットに反映されにくいことがわかりました。また、要件の解像度が低い状態でInceptionを始めると、議論が発散しやすくなります AI-DLCのInceptionに入る前に、ビジネス背景や目的を整理するステップが必要だと感じました。 仕様とAI実装のギャップ Inceptionフェーズで仕様を決め切った上でも、以下の2つの問題が発生しました。 仕様の記載漏れ: Inceptionフェーズで決めた仕様に漏れがあり、Constructionフェーズで初めて気づくケース。例えば、APIレスポンスのラッパー形式やお気に入り店舗のパラメータなど、実装段階で判明した考慮漏れがありました 仕様通りに実装されない: 仕様として記載されているにもかかわらず、AIが異なる実装をするケース。例えば、既存の認証方式と異なるパターンで実装したり、既存のアーキテクチャパターンに従わない実装が生成されることがありました 前者は要件定義やアプリケーション設計の精度を上げていく必要があります。今回検証だったので細部まで確認できていないところがありました。そのため、実業務に導入した場合はよりこの部分に時間を使うべきだと思いました。 後者はモデルの進化を待ちつつ、コンテキストの渡し方の工夫や、実装が仕様に準拠しているかを監査するサブエージェントの整備など、ガードレールを張っていくことが必要だと感じました。 コンテキスト管理の課題 AIツール固有の課題として、コンテキスト管理の難しさがあります。実装フェーズではコードの読み書きが多く発生するため、auto-compact(コンテキストの自動圧縮)が頻発しました。その結果、audit.mdへの書き込みが不安定になったり、要件定義ファイルへの指摘を繰り返してもアウトプットに反映されないことがありました。 対策として、コンテキストの使用量を抑えるためにルールファイルを分割して必要なタイミングでのみ読み込む方式にしたり、サブエージェントを活用して処理を分散させるなどの工夫が必要です。 レビュー負荷への対応 AIのアウトプット量が増えることで、人間のレビュー負荷が増大するという課題があります。この課題に対しては、以下のアプローチを検討しています。 レビューを軽減するプロセスの構築: 自動テストやLintの活用 AIの出力品質を上げる工夫: プロンプトの改善、ルールの整備 段階的なレビュー: 各ステージでの承認による分散 これらの最適解は、チームやプロダクトによって異なるため、継続的に改善していく必要があります。 最後に AI-DLCは、AIを活用した開発における「ボトルネックを特定し、解消していく」ためのフレームワークとして有望だと感じています。 今回見えてきた課題はAI-DLCのフレームワーク自体の問題ではなく、AIと人間が協働する上で必然的に発生する問題です。今後も継続的に活用しながら、チームに最適な形にカスタマイズしていきたいと考えています。
この記事は every Tech Blog Advent Calendar 2025 の 27 日目の記事です。 はじめに こんにちは。リテールハブ開発部の清水です。 私たちは小売向けサービスをLaravelで開発しています。 このプロジェクトではGit hooksのpre-commit設定を使用してコミットのタイミングでLaravel Pint, Larastanを呼び出すことでコード品質を整えるための仕組みを使用しています。 この仕組みのベースは、プロジェクト初期に整備されたものを引き継いだもので、今回その内容を見直しながら整理しました。 ちょうど良い機会でしたので、本記事で私たちが使用している設定内容をご紹介いたします。 Git hooksとは? Git hooksとは、git commit や git push などの Git 操作をきっかけに、自動でスクリプトを実行できる仕組みです。 コミット前にチェック処理を挟むなど、人の操作ミスを防ぐための自動処理を組み込む用途で使われます。 https://git-scm.com/docs/githooks Laravel Pintとは? Laravel Pint は、Laravel公式が提供している PHPコードの自動フォーマッターです。 決められたコーディング規約(Laravel / PSR-12 など)に従って、PHPコードの書き方を自動的に統一します。 https://laravel.com/docs/12.x/pint Larastanとは? Larastan は、PHP の静的解析ツール PHPStan を Laravel 向けに拡張したツールです。 コードを実行せずに解析し、存在しないプロパティや型の不整合などの問題を事前に検出します。 https://github.com/larastan/larastan コミットを行った時の処理の流れ git commitを実行すると、Git hooksのpre-commitフックが起動 コミット対象のPHPファイルを取得 Laravel Pintによるフォーマットチェック Larastanによる静的解析 3 or 4のチェックでエラーが検出された場合、コミットを中断 全てのチェックをパスした場合のみ、コミットが完了 pre-commit設定内容 #!/bin/sh set -eu # --- 1) コミット対象(ステージ済み)のPHPファイルだけ拾う --- php_files=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.php$' || true) # PHPファイルがなければ何もしない if [ -z "$php_files" ]; then exit 0 fi echo "コミット対象のPHPファイルをチェックしています..." # --- 2) Pint:フォーマットチェック(修正はしない) --- echo "Pintでフォーマットをチェックしています..." if ! echo "$php_files" | xargs ./vendor/bin/pint --test; then echo "" echo "❌ フォーマットエラーがあります。" echo " 以下のコマンドで修正してください:" echo " make lint" exit 1 fi echo "✓ フォーマットチェック OK" # --- 3) Larastan:静的解析 --- if echo "$php_files" | grep -qE '^app/'; then echo "Larastanで静的解析を実行しています..." if ! ./vendor/bin/phpstan analyse --no-progress --memory-limit=1G; then echo "" echo "❌ 静的解析エラーがあります。" echo " エラーを修正してから再度コミットしてください。" exit 1 fi echo "✓ 静的解析 OK" fi echo "" echo "✓ 全てのチェックが完了しました。" exit 0 Makeコマンドの紹介 コミットのタイミングだけではなく、手動でLaravel Pint, Larastanを実行したい場面もあります。 以下のMakeコマンドで実行できるようにしています。 # コードスタイルチェック&修正 lint: @files=$$(git diff --cached --name-only --diff-filter=ACM | grep "\.php$$" | sed "s|^$$(basename $$(pwd))/||"); \ if [ -n "$$files" ]; then \ docker compose -f $(COMPOSE_FILE) exec -T $(CONTAINER_PHP) sh -c "./vendor/bin/pint $$files"; \ else \ echo "ステージされたPHPファイルがありません"; \ fi # コードスタイルチェック lint-check: @files=$$(git diff --cached --name-only --diff-filter=ACM | grep "\.php$$" | sed "s|^$$(basename $$(pwd))/||"); \ if [ -n "$$files" ]; then \ docker compose -f $(COMPOSE_FILE) exec -T $(CONTAINER_PHP) sh -c "./vendor/bin/pint --test $$files"; \ else \ echo "ステージされたPHPファイルがありません"; \ fi # 静的解析 larastan: docker compose -f $(COMPOSE_FILE) exec $(CONTAINER_PHP) ./vendor/bin/phpstan analyse --memory-limit=1G 実際にコミットする流れ Laravel Pint, Larastanで弾かれる内容のコードを作成 <?php namespace App\Http\Controllers; // importが名前順になっていない use Retailapp\Common\Models\User; use Illuminate\Http\JsonResponse; use App\Http\Controllers\Controller; class TestController extends Controller { public function index () : JsonResponse { $ user = User :: find ( 1 ) ; $ name = $ user -> undefined_property; // 存在しないプロパティを呼び出している return response () -> json ([ 'name' => $ name ]) ; } } コミットを試みると、フォーマットエラーで弾かれる % git commit -m '弾かれてほしいコミット' コミット対象のPHPファイルをチェックしています... Pintでフォーマットをチェックしています... ⨯ ──────────────────────────────────────────────────────────────────── Laravel FAIL ............................................. 1 file, 1 style issue ⨯ app/Http/Controllers/TestController.php no_unused_imports, ordered_import… ❌ フォーマットエラーがあります。 以下のコマンドで修正してください: make lint pintで自動的に修正 % make lint ✓ ──────────────────────────────────────────────────────────────────── Laravel FIXED ...................................... 1 file, 1 style issue fixed ✓ app/Http/Controllers/TestController.php no_unused_imports, ordered_import… もう一度コミットすると、今度はLarastanで弾かれる % git commit -m '弾かれてほしいコミット' コミット対象のPHPファイルをチェックしています... Pintでフォーマットをチェックしています... ──────────────────────────────────────────────────────────────────── Laravel PASS ............................................................ 1 file ✓ フォーマットチェック OK Larastanで静的解析を実行しています... ------ -------------------------------------------------------------------------- Line Http/Controllers/TestController.php ------ -------------------------------------------------------------------------- :14 Access to an undefined property Retailapp\Common\Models\User::$undefined_property. 💡 Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property ------ -------------------------------------------------------------------------- [ERROR] Found 1 error ❌ 静的解析エラーがあります。 エラーを修正してから再度コミットしてください。 Larastanに違反する部分を修正 <?php namespace App\Http\Controllers; use Illuminate\Http\JsonResponse; use Retailapp\Common\Models\User; class TestController extends Controller { public function index () : JsonResponse { $ user = User :: find ( 1 ) ; $ name = $ user -> name ; // 修正 return response () -> json ([ 'name' => $ name ]) ; } } コミット成功 % git commit -m '通ってほしいコミット' コミット対象のPHPファイルをチェックしています... Pintでフォーマットをチェックしています... . ──────────────────────────────────────────────────────────────────── Laravel PASS ............................................................ 1 file ✓ フォーマットチェック OK Larastanで静的解析を実行しています.. [OK] No errors ✓ 静的解析 OK ✓ 全てのチェックが完了しました。 おわりに 本記事では、私たちの Laravel プロジェクトで使用している Git hookのpre-commit 設定と、その中で Laravel Pint・Larastan をどのように組み込んでいるかをご紹介しました。 同様の仕組みを検討されている方の参考になれば幸いです。 最後までお読みいただきましてありがとうございました。
動画
該当するコンテンツが見つかりませんでした














