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

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

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

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Laravel 5

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

Q&A

解決済

2回答

1878閲覧

多対多リレーションと中間テーブルの考え方について

miyu94

総合スコア18

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Laravel 5

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

0グッド

1クリップ

投稿2019/02/23 12:04

編集2019/02/23 12:37

多対多リレーションの認識で曖昧な部分があります。

「モデルAとモデルBが、多対多関係である」とは「あるAは複数のBを持つことができ、あるBは複数のAを持つことができる」関係だと認識しています。

この認識は正しいでしょうか?

よくSNSにある以下の機能は多対多ですか?

・ユーザー(User)が投稿(Post)に「いいね」する機能
・ユーザー(User)が他のユーザー(User)を「フォロー」する機能

これらの機能をLaravel標準の多対多リレーションを使わずに実装したら、いろんな問題が発生したので、多対多で実装すべきだと思いました。

フォロー機能は、両モデルが同じUserですが多対多になりますか。

これらの機能を実装するスタンダードなやり方を知りたいです。
以下のやり方は正しいでしょうか?

「いいね」機能

中間テーブルのカラムは user_id, post_id です。

PHP

1//Userクラス 2public function posts() 3{ 4 return $this->belongsToMany('App\Post'); 5} 6 7//Postクラス 8public function users() 9{ 10 return $this->belongsToMany('App\User'); 11}

「フォロー」機能

ユーザーのフォロー一覧、フォロワー一覧、相互フォロー一覧などを取得できることが前提です。

中間テーブル follows のカラムは user_id, follow_user_id です。

PHP

1//Userクラス 2 3//自分がフォローしているユーザーを取得 4public function my_follow_users() 5{ 6 return $this->belongsToMany('App\User', 'follows', 'user_id', 'follow_user_id'); 7} 8//自分のフォロワーを取得 9public function my_follower_users() 10{ 11 return $this->belongsToMany('App\User', 'follows', 'follow_user_id', 'user_id'); 12}

相互フォローの取得は複雑になりそうです。

その他疑問

Laravelでいいね機能を作ってみた
この記事のように「いいね」実装に多対多を使わない例を見るのですが、どちらが良いでしょうか?
中間テーブルのモデルクラス内にもリレーションメソッドを記述しているようです。

中間テーブルのモデルLikeに、postメソッドとuserメソッドをbelongsToで定義。 Userモデルに、likesメソッドをhasManyで定義。 Postモデルに、userメソッドをbelongsTo、likesメソッドをhasManyで定義。

・中間テーブルの2カラム(例 user_id, post_id)は外部キー制約を付け、かつユニーク制約をつけるべきですか?

質問が多くてすみません。ご回答いただけると幸いです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

「モデルAとモデルBが、多対多関係である」とは「あるAは複数のBを持つことができ、あるBは複数のAを持つことができる」関係だと認識しています。

この認識は正しいでしょうか?

正しいです。

よくSNSにある以下の機能は多対多ですか?

はい。

この記事のように「いいね」実装に多対多を使わない例を見るのですが、どちらが良いでしょうか?

ケースバイケースですが、基本的にIDカラムしかない場合はBelongsToManyを使えば良いでしょう。
この前同じような質問がありました。
https://teratail.com/questions/169935

・中間テーブルの2カラム(例 user_id, post_id)は外部キー制約を付け、かつユニーク制約をつけるべきですか?

ユニーク制約は不要です。
例えば、例に上げてらっしゃる「いいね」機能で考えると、同じユーザーが複数の投稿にいいねする(中間テーブルにuser_idが複数回挿入される)可能性があるからです。
外部キー制約は基本的につけたほうが良いでしょう。

投稿2019/02/25 07:02

xenbeat

総合スコア4258

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

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

miyu94

2019/02/26 15:24

ありがとうございます。 > 基本的にIDカラムしかない場合はBelongsToManyを使えば良いでしょう。 中間テーブルのことですよね?いいねの例だと user_id と post_id の2カラムのことですね。 IDの2カラム + created_at の3カラムだとどうでしょうか? > ユニーク制約は不要です。 説明不足で申し訳ございません。「組み合わせ」のユニーク制約のことです。
miyu94

2019/02/26 15:30

BelongsToManyでないと実現するのが難しい場面が多くて、 できればBelongsToMany使いたいですね。
xenbeat

2019/02/26 21:27

> 中間テーブルのことですよね? はい、IDカラムしかない中間テーブルのことです。 > IDの2カラム + created_at の3カラムだとどうでしょうか? created_atのようなWHOカラムがあったとしてもBelongsToManyでよろしいかと思います。 IDおよびWHOカラムしかない中間テーブルは作成、削除がほとんどで更新はほぼないと考えられるためです。 非正規化された中間テーブルやステータスカラムを持つ中間テーブル(例:友達申請に使用するテーブル)等に関しては柔軟性や拡張性が求められたりするので、hasMany, belongsToを使うほうがよろしいかと思います。 > 説明不足で申し訳ございません。「組み合わせ」のユニーク制約のことです。 あーなるほど。個人的にはアプリの実装に頼るだけでなくDBレベルでも制約(外部キー制約、ユニーク制約等)をつけることをおすすめします。 ただ、プロジェクト規約・性質によりDBによる制約はつけないこともありますので、必須ではないという回答になります。
miyu94

2019/02/28 12:34

BelongsToManyで注意するのは、中間テーブルの更新処理が発生する場合なのですね。 制約に関しては、必須ではないが付けるのが無難ということですね。 ありがとうございました!
guest

0

この記事のように「いいね」実装に多対多を使わない例を見るのですが、どちらが良いでしょうか?

多対多は柔軟に対応できる反面、実装が複雑になったり整合性を取るのが大変になりがちです。
もし多対多を使わないで済むなら使わないにこしたことはないと思います。

以下の記事を読ませていただきましたが、特に違和感もありませんし、この実装を参考にして良いと思います。

Laravelでいいね機能を作ってみた

投稿2019/02/25 10:35

nskydiving

総合スコア6500

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

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

miyu94

2019/02/26 15:35

多対多は便利な反面、複雑になりがちなのですね。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問