質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

Q&A

解決済

1回答

3332閲覧

Laravelで中間テーブルの値を取得したい

kafetora

総合スコア13

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Laravel 5

Laravel 5は、PHPフレームワークLaravelの最新バージョンで、2014年11月に発表予定です。ディレクトリ構造がが現行版より大幅に変更されるほか、メソッドインジェクションやFormRequestの利用が可能になります。

0グッド

1クリップ

投稿2019/01/08 12:20

Laravelを使用した顧客管理システムを作成しており、顧客ごとに訪問記録をつけようとしています。
訪問記録には訪問したスタッフを入力する必要があり、一人の場合もあれば複数人の場合もあります。

スタッフごとに自分の訪問記録も表示させたいので、訪問記録テーブル(visit_log)ととスタッフテーブル(staff)の多対多リレーション(visitlog_staff)を作成しました。

顧客の詳細ページにて訪問記録の一覧を表示させるために、顧客IDに紐づいた訪問記録をvisit_logから取得した後、visitlog_staffからvisit_log_idをもとにstaff_idを取得したいのですが、いまいちやりかたがわかりません。

なお、訪問記録を新規追加した際に、訪問スタッフに対応した中間テーブルへの保存は出来ています。

手書きのSQLで強引に取得することは可能ですが、フレームワークに沿った方法を教えていただきたい所存であります。

ご教授のほどよろしくお願いいたします。

環境とテーブル構成、関連ファイルは以下の通りです。

Laravel5.6

###visit_logs

idclient_idvisited_date
1232019-01-03
2232019-01-03
3232019-01-03
4232019-01-03

###staff

idname
1佐藤
2田中
3鈴木

###visitlog_staff
このテーブルのstaff_idをvisit_log_idをもとに取得したいです。

idvisit_log_idstaff_id
112
213
321
432

###VisitLog.php

namespace App; use Illuminate\Database\Eloquent\Model; class VisitLog extends Model { public function staff(){ return $this->belongsToMany('App\Staff', 'visitlog_staff', 'visit_log_id', 'staff_id'); } }

###Staff.php

namespace App; use Illuminate\Database\Eloquent\Model; class Staff extends Model { public function visitlogs(){ return $this->belongsToMany('App\VisitLog', 'visitlog_staff'); } }

###VisitLogController.php
訪問記録を追加する際に使用しています。

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\VisitLog; class VisitLogsController extends Controller { public function store(Request $request, \App\Client $oClient){ $visitlog = new VisitLog(); $visitlog->client_id = $oClient->id; $visitlog->visited_date = $request->visited_date; $visitlog->save(); $visitlog->staff()->attach($request->visitlog_staff); return redirect('/client/' . $oClient->id)->with('message', '訪問記録を追加しました'); } }

###ClientsController.php
showclientの引数にはclient_idが入ります
顧客ごとの訪問記録一覧はこのshowclientメソッド内で取得し、viewに渡したいのですがどう書けばいいのかわかりません。。。

namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Client; use App\Staff; use App\VisitLog; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\DB; use App\Http\Requests\ClientRequest; use Illuminate\Support\Facades\Auth; class ClientsController extends Controller { public function showclient($id){ $oClient = Client::findOrFail($id); $oVisitLog = VisitLog::where('client_id', $id)->get(); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

現在手元に環境がないので、下記コードは全て未検証です。。。上手く行かなかったら、すみません^^;
回答した内容は、マニュアル(laravel5.7):リレーションにも、同じ内容が書いてありますので、そちらもご確認くださいねー。


モデルのリレーション定義は、関数名をプロパティとして参照することでデータが取得できますよ。

php

1$oVisitLog = VisitLog::where('client_id', $id)->get(); 2foreach($oVisitLogs as $l){ 3 foreach($l->staff as $s){ 4 //スタッフの名前 5 $s->name; 6 } 7}

こんな感じです。

ただし、この書き方だと$oVisitLogには、あくまで「visit_logsのデータのみ」が返却されており、staffのデータは未取得の状態です。
なので、$l->staffは参照された時点でSQLを実行してデータを取ってくることになります。
つまり、取得されたvisit_logsの行数が増えた分だけSQLの実行回数が増えていくのです。

こういう場合は、予め使うことが分かっているstaffを、visit_logsを取得した時に一緒に取得するようwith()で指定することができます。

php

1$oVisitLog = VisitLog::with('staff')->where('client_id', $id)->get(); 2foreach($oVisitLogs as $l){ 3 foreach($l->staff as $s){ 4 //スタッフの名前 5 $s->name; 6 } 7}

参照する部分などの書き方は、with()を指定しない時とまったく同じなので、見た目だけでは差が分かりにくいのですが、$oVisitLogには、visit_logsのデータとそれに紐づくstaffのデータが「取得済み」の結果が返却されます(SQLの実行回数も最低限で済むよう、laravelが良きに計らってくれます)。


余談ですが。
clientsと、visit_logsにもリレーション関係がありますので、どうせならClientモデルにそれを定義してもいいかもしれません。

class Client extends Model { public function visitlogs(){ return $this->hasMany('App\VisitLog'); } }

さらに、with()は、ネストしたリレーションまで取得するように「.」で繋げて指定できますので

php

1class ClientsController extends Controller 2{ 3 4 public function showclient($id){ 5 $oClient = Client::with('visitlogs.staff')->findOrFail($id); 6 $oVisitLog = $oClient->visitlogs; 7 } 8 9}

これで、clientの情報と、そのvisit_logs(staffデータ付き)まで、一括で取得できるハズです。。。。(多分)

投稿2019/01/09 07:57

mix-peach

総合スコア1910

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kafetora

2019/01/31 11:05

返事が遅くなってしまい、申し訳ありません。 動作の確認が出来ました! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問