🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Laravel

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

Q&A

1回答

1413閲覧

laravel お知らせの未読のみをモデルで持たせたい 多対多のリレーション

creative_09

総合スコア80

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Laravel

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

0グッド

0クリップ

投稿2021/02/25 02:01

編集2021/02/25 02:28

laravelのモデルで多対多のリレーションで存在しないものを取得したい
announce_readsテーブルにuser_idがないものを取得するための多対多のリレーションの貼り方を教えて下さい。

以下のようにUserモデルへ多対多のリレーションを組み、
$user->announceNonReads
とした場合は既読の一覧が表示できましたが、
未読の一覧を取得したいので、
announce_readsテーブルにuser_idがないものを取得したいです
その場合はどのように記述すればいいのでしょうか?

public function announceNonReads() { return $this->belongsToMany( 'App\AnnouncePost', //関係するモデル 'announce_reads', //中間テーブルのテーブル名 'user_id', //中間テーブル内で対応しているID名 'announce_post_id' //関係するモデルで対応しているID名 ); }

テーブルを追記します

AnnouncePostテーブル id title body Userテーブル id name AnnounceReadテーブル id announce_post_id user_id となっています

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

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

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

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

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

m.ts10806

2021/02/25 02:02

まず、SQLで自前で組めますか?
phper.k

2021/02/25 02:12

テーブルの定義はどうなっていますか?
creative_09

2021/02/25 02:24

ありがとうございます。 SQLで組むのは難しいです。existsや、where inなどで試行錯誤中です。
creative_09

2021/02/25 02:28

テーブルの定義を追記しました。 よろしくお願いします
phper.k

2021/02/25 02:46

create文で提示してください。
m.ts10806

2021/02/25 03:21

せめてER図くらいは簡単にでも書けて理解できないとフレームワークでDBからめたサービス作るのは難しいと思います。
creative_09

2021/02/25 03:57

doesntHaveを使えるのかはわかりませんが、 belongsToManyでuser_idに該当がなかったものだけをリレーションする記述を知りたかったのですが、 シンプルにnotやなにかlaravel特有のもので解決できないか、相談したかったのです。
phper.k

2021/02/25 04:06

できなくはない。 ただし、あなたの力量からして、概念だけ説明したところで、やりとりをくりかえすことになると思います。 それは回答者にとって負担が大きい。 そのものズバリで実行できる回答をしようと思うと、粒度の細かな情報が必要です。
creative_09

2021/02/25 04:15

ありがとうございます。 なるほど。そういうことなんですね。 一応、モデルには持たせずに、コントローラーから AnnouncePost::doesntHave('Read')のように取得していたので モデルに持たせる場合はどうなるのか知りたかったのです。 ですが、おっしゃるとおり、モデルのリレーションの書き方のみで、user_idが該当しないもののみをリレーションするというのは敷居が高そうなので、また調べてからにします。ヒントになるようなことがありましたら、また回答頂ければ嬉しいです
guest

回答1

0

あるユーザーの未読一覧を取得したいという状況なのかなと思いますが、
AnnouncePostクラスにリレーションを追加するのはいかがでしょうか。

AnnouncePostクラス

php

1/** 2 * このお知らせを読んだユーザー 3 */ 4public function readUsers() 5{ 6 return $this->belongsToMany(User::class, 'announce_reads'); 7}

このリレーションを使うと以下のような感じで取得できないでしょうか。

php

1use Illuminate\Database\Eloquent\Builder; 2 3$user = // 対象のユーザー 4 5$posts = AnnouncePost::whereDoesntHave( 6 'readUsers', 7 function (Builder $query) use ($user) { 8 $query->where('user_id', $user->id); 9 } 10)->get();

(もっと簡単にできるといいのですが・・・)

投稿2021/02/25 04:39

Lulucom

総合スコア1899

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

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

phper.k

2021/02/25 04:45

その条件だと常に結果0件になると思いますよ
Lulucom

2021/02/25 04:48

すみません、確認いたします。ご指摘ありがとうございます。
Lulucom

2021/02/25 06:02

簡単なデータでの確認ですが取れることは確認しました。質問に掲載されているテーブル名等と全く同じにしての再確認です。バージョンが不明でしたのでLaravel 8で試しました。
phper.k

2021/02/25 06:15 編集

既読かどうかの判別がないようですが・・・ もっとも、命題に不明点が多すぎて回答のしようがないのですけども。 中間テーブルのレコードの意味の説明が必要。 解釈によっては - 中間テーブルは、既読のレコードである - 中間テーブルは、読むべき記事を紐づけるレコードである どちらとも解釈できる 特定しないと回答できません。
Lulucom

2021/02/25 06:28 編集

ありがとうございます。既読のものがannounce_readsに登録されていると思いますので、そこに無い、という判別にしました。もしかしてこの前提が間違ってますでしょうか 汗 確かにそこが特定できないと回答できませんでした。早とちりでした。ありがとうございます。
phper.k

2021/02/25 06:21 編集

質問者の説明が不足しているのでなんとも言えないなと思ってます。 そこが確定できないから、修正依頼をしているので。 しかも、その前提を質問者と共通認識にしないと、回答しても無駄になっちゃいますので。
phper.k

2021/02/25 06:23

ただ、この要件だと、リレーションにしちゃうと 1+N が避けられないだろうと思いますね。
Lulucom

2021/02/25 06:31 編集

ユーザー一覧などで未読を表示したいのだとすると、何か別のやり方が良いのかもしれませんね。
creative_09

2021/02/25 12:37

ありがとうございます。 参考になりそうな答えも頂き嬉しいです また、中間テーブルである、announce_readsは Lulucomさんのおっしゃるとおり、 既読されたときに記録されるテーブルとしています。 まだ、提示していただいたコードを解読できていないレベルですので、じっくり解読しようと思います またご連絡します。
creative_09

2021/02/25 12:41

リレーションで中間テーブルである、announce_readsにuser_idがあれば既読 なければ未読、そのような形をリレーションで自分が知らないだけで簡単にできると思いこんでいました。 既読は多対多のリレーションでできるのですが。
Lulucom

2021/02/25 13:45 編集

中間テーブルannounce_readsに、既読/未読の状況を保持するカラムを設けたりすればできそうな気はしますが、お知らせが発生する度にユーザー毎に未読レコードを作成する必要が出てきますしね・・・
creative_09

2021/02/25 14:24

ありがとうございます。 なかなかモデルに持たせるのは非現実なのですかね。。。 上記のコードのように、モデルでは多対多をはっておき、コントローラー側で doesntHaveやhasを使ってそれぞれ取得することにします
Lulucom

2021/02/25 14:54 編集

AnnouncePostのローカルスコープにしておくと多少はすっきりするのかなと思いました。 // ローカルスコープ public function scopeUnreadByUser($query, User $user) { return $query->whereDoesntHave('readUsers', function ($query) use ($user) { $query->where('user_id', $user->id); }); } // ローカルスコープを使う $posts = AnnouncePost::unreadByUser($user)->get(); 他に良い回答が来ると良いのですが・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問