はじめに
こんにちは、未経験からエンジニア転職を目指しているものです。
オンラインスクールで本格的に学習して7ヶ月目に入りました。
PHP,Laravelを学習しポートフォリオを作成中です。
Postモデルに紐づいているMapInfoモデルのリレーションに悪戦苦闘したため、解決までの内容を整理しました。
概要
Laravel Sailを使った開発環境で、Google Maps APIを利用して地図を描画しました。
新規投稿作成画面に無事、地図情報が反映されるようになりましたが、
PostモデルとMapInfoモデルが紐づいた事で、新たな問題が発生しました。
1. 投稿した内容が、投稿一覧に反映されず、〇〇のエラーが発生
2. 1.の解決後、投稿編集画面を作成したが、updateが機能しない
*2.については別投稿で説明予定
投稿した内容が、投稿一覧に反映されず、エラーが発生
ディレクトリ構成としては下記になります
- post.blade.php : 新規投稿画面
- index.blade.php :投稿一覧画面
処理の流れは下記になります。
- post.blade.phpでform内容を投稿
- PostControllerのstoreメソッドが機能
- データベースに保存
- PostControllerのindexメソッドが機能
- index.blade.phpへ遷移し正しく表示される
しかし、投稿ボタンをクリックしたら添付のエラーが発生してしまいました。
原因の特定に向けた検証 part1
データベースには確かに投稿の内容が保存されていることを確認
PgAdminのクエリツールで以下を実施し確認
SELECT * FLOM posts;
SELECT * FLOM map_infos;
→このことから、PostControllerのstoreメソッドは機能している事を確認
原因の特定に向けた検証 psrt1
PostControllerのstoreメソッドが機能していないと仮説。
実行内容:
PostController.phpのindexメソッド内を return "Post Index is working."; に変更
結果:
ブラウザ上に Post Index is working と表示された(下記の状態)
考察:
indexメソッドが機能していない訳ではない。
原因の特定に向けた検証 psrt2
検証ツールのネットワーク画面で302のエラーと失敗の表示を確認
失敗の表示は何度もされる
仮説:
- indexメソッドがデータサーバーからアクセスするときに何かしらのエラーが起きている
→上記と、今回の事象が見られるようになったのが、PostモデルとMapInfoモデルのリレーションが成功しだしてからである事から、モデル部分に重点をおいて再検証を実施
原因解明:
- protected $with = ['mapInfo'];をコメントアウトして無効化を実施
- Eager Loading(関連データの自動読み込み)を無効にし、PostモデルをロードするときにMapInfoモデルのデータを自動的に取得させないように変更
- 上記実行後、無事にindex.blade.phpへ遷移し、投稿一覧画面が表示されるように。
原因の考察
Postモデルに関連するMapInfoデータが存在しない、もしくは正しく紐づいていない状態でEager Loadingを実行すると、Laravelが関連データを探しに行き、データベースに無駄な負荷がかかる。データが不完全な場合、サーバーがタイムアウトしたり、例外がスローされる可能性がある。
今回のケースでは、map_infosテーブルにある一部のデータがpost_idと正しく紐づいていない(nullの値がある)ことが原因で、Eager Loadingが期待通りに動作していなかったと考えられる。
まとめ
データベースでリレーションが絡むと、問題が複雑になる。
どの動きの過程で問題が起きているかを、一つずつ洗い出す事が大切である。
最後まで、ご視聴頂きありがとうございます。