0.はじめに
前回に引き続きポリモフィック関連の記事を書きます。
今回はポリモフィック関連のデータの取得の記事になります。
1.目次
0.はじめに
1.目次
2.この記事を読んだらわかること
3.DB の確認
4.子に条件を与えた親のデータを取得
5.親に条件を与えた子のデータの取得
6.さいごに
7.参考
2.この記事を読んだらわかること
条件をもたせたポリモフィック関連のデータの取得
- 子供側のデータの取得方法
- 親側のデータの取得方法
3.DB の確認
テーブルの関係性
どのようなデータを使用するかは、前回の記事をご確認頂けますと幸いです。
ざっくり言うと、
commnet(子)が、video(親)と post(親)をもっている関係となります。
ER図で表すとこんな感じです
次に、DB の中はこのようになっています。
posts のデータ
id | title | body |
---|---|---|
1 | コメントなしタイトル | コメントなし本文 |
2 | post_title1 | post_body1 |
3 | タイトル1 | 投稿本文1 |
4 | post_title2 | post_body2 |
videos のデータ
id | title | url |
---|---|---|
1 | コメントなしタイトル | http://video_title/video/1 |
2 | video_title1 | http://video_title/video/1 |
3 | タイトル1 | http://video_title/video/2 |
4 | video_title2 | http://video_title/video/3 |
comments のデータ
id | body | commentable_id | commentable_type |
---|---|---|---|
1 | コメント作成1 | 2 | App\Models\Post |
2 | コメント作成2 | 3 | App\Models\Post |
3 | コメント作成3 | 2 | App\Models\Video |
4 | コメント作成4 | 3 | App\Models\Video |
5 | コメント作成5 | 4 | App\Models\Post |
6 | コメント作成6 | 4 | App\Models\Video |
4.子に条件を与えた「親のデータを取得」
以下の内容は公式ドキュメントを参考にしております。
簡単なデータの取得からいってみたいと思います。
comment(子) を持っている post(親) を取得する
まずは、親(Post)が子(comment)持っているデータを取得
use App\Models\Post;
$posts = Post::has('comments')->get();
取得したデータは、
=> Illuminate\Database\Eloquent\Collection {#4602
all: [
App\Models\Post {#4607
id: 2,
title: "post_title1",
body: "post_body1",
},
App\Models\Post {#4350
id: 3,
title: "タイトル1",
body: "投稿本文1",
},
App\Models\Post {#3990
id: 4,
title: "post_title2",
body: "post_body2",
},
],
}
となます。
ここで、注意しなといけないのは、
id が 1 のデータがないことです。
これは、Post::has('comments')
の通り、
comment のデータを持っている post のデータを取得しているためです。
comment(子) を持っていない post(親) は取得できません。
comment(子) に条件を与えて post(親) を取得する
comments テーブルの id が 1 を持っている post のデータを取得
use App\Models\Post;
use Illuminate\Database\Eloquent\Builder;
$posts = Post::whereHas(
'comments',
function (Builder $query) {
$query->where('comments.id', '=', 1);
}
)->get();
取得したデータは、
=> Illuminate\Database\Eloquent\Collection {#4616
all: [
App\Models\Post {#4613
id: 2,
title: "post_title1",
body: "post_body1",
},
],
}
となります。
comments テーブルの id が 1
を持っている post のデータを取得するコードとなります。
whereHas
メソッドを使うと複雑な条件を定義することができます。
whereHas
メソッドの説明
- 第1引数には、
リレーション先のテーブル名
- 第2引数には、
リレーション先の取得したいデータの条件のコールバック関数
を記述します。
それでは、comments テーブルの comment の id が 1 のデータを確認してみます。
id | body | commentable_id | commentable_type |
---|---|---|---|
1 | コメント作成1 | 2 | App\Models\Post |
commentable_id が 2
、
commentable_type が App\Models\Post
となっています。
これは、親が何かを表しています。
-
commentable_id
は、親の id -
commentable_type
は、親のタイプ(※ Model の情報)
を示しています。
なので、
comments テーブルの id が 1 、post テーブル の id が 4
のデータを持っているということを示しています。
posts の id が4
のデータは、
id | title | body |
---|---|---|
2 | post_title1 | post_body1 |
となっており、取得したデータとテーブルが一致していることがわかるかと思います。
5.親に条件を与えた「子のデータの取得」
それでは、次に子側のデータの取得に方法に入りたいと思います。
post(親) や video(親) に条件を与えた comment(子) を取得する
ポリモフィック関連の親(post や video)に条件を与えた子(comment)のデータの取得
早速、コードを見てみましょう。
use App\Models\Comment;
use App\Models\Post;
use App\Models\Video;
use Illuminate\Database\Eloquent\Builder;
$comments = Comment::whereHasMorph(
'commentable',
[Post::class, Video::class],
function (Builder $query) {
$query->where('title', '=', 'タイトル1');
}
)->get();
取得したデータは、
=> Illuminate\Database\Eloquent\Collection {#4613
all: [
App\Models\Comment {#4597
id: 2,
body: "コメント作成2",
commentable_id: 3,
commentable_type: "App\Models\Post",
},
App\Models\Comment {#4611
id: 4,
body: "コメント作成4",
commentable_id: 3,
commentable_type: "App\Models\Video",
},
],
}
となります。
これは、
親の Post と Video の title カラムが タイトル1
を持っている子の Comment を取得しています。
ポリモフィック関連で親に条件を持たすことができているのは、
whereHasMorph
メソッドになります。
whereHasMorph
メソッドの説明
- 第1引数には、CommentModel で定義した
ポリモフィック先のデータを取得するメソッド
(Laravel でポリモフィック関連の Factory を作成してみた参照) - 第2引数には、
ポリモフィック関連の親のクラス
※ 今回は、複数の親のデータを取得しているが、単数の親でも問題ありません。
ただ単数の場合は、array 型ではなく、string 型でOKです。 - 第3引数には、
リレーション先の取得したいデータの条件のコールバック関数
を記述しています。
title カラムが タイトル1
を持っている Post::class, Video::class は、下記のとおりです。
Post::class
id | title | body |
---|---|---|
3 | タイトル1 | 投稿本文1 |
Video::class
id | title | url |
---|---|---|
3 | タイトル1 | http://video_title/video/2 |
上記のデータを持っている comment は
id | body | commentable_id | commentable_type |
---|---|---|---|
2 | コメント作成2 | 3 | App\Models\Post |
4 | コメント作成4 | 3 | App\Models\Video |
となっており、取得したデータとテーブルが一致していることがわかるかと思います。
commentable_id
が 親の Post::class, Video::class の id 、
commentable_type
が Post::class, Video::class を示しています。
6.さいごに
ポリモフィック関連先の条件にコールバック関数をつかっているので複雑に感じましたが、
「どこから」「どんな条件」でデータを取得するかの基本が掴めていたら理解することができるのかなと感じました。
とか言いつつ、私自身もこれを理解するのに時間がかかりました。
今回は、条件は1つしかありませんが、
コールバック関数内で複数の条件をもたせて、もっと複雑な処理をすることができます。