laravel5.7で、user同士をフレンズ化するのに多対多のリレーションを作ってみた
1, 多対多のリレーションには、中間テーブルが必要
※命名規約的には、users_usersテーブルだけど、friendsテーブルの方が分かりやすい
1 |
php artisan make:model friends --all |
1 2 3 4 5 6 |
Schema::create('friends', function (Blueprint $table) { $table->increments('id'); $table->unsignedInteger('user_id')->comment('自分のユーザID'); $table->unsignedInteger('friend_id')->comment('友達のユーザID'); $table->timestamps(); }); |
2, laravelで多対多のリレーションは、BelongtoManyを使う
app\User.php
1 2 3 4 5 |
// 自分の友だちリスト function friends() { return $this->belongsToMany('App\User', 'friends', 'user_id', 'friend_id'); } |
3, factoryでseeder
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public function run() { // 適当な人数のuser生成 factory(App\User::class, 10)->create(); //全ユーザに、ランダムに3人のフレンズをもたせる foreach (App\User::All() as $user){ $random_friends_id = App\User::inRandomOrder() ->where('id', '<>', $user->id) //自分以外 ->take(3) //友達の数 ->pluck('id')->toArray();//user->idだけ配列化 // 多対多の時はsave()ではなく、attach(配列)で保存する $user->friends()->attach( $random_friends_id ); } } |
4, 画面に表示してみる
HomeController.php
1 2 3 4 5 6 |
public function index() { // 友達リスト $friends = Auth::User()->friends()->get(); return view('home', compact('friends')); } |
home.blade.php
1 2 3 |
@foreach($friends as $friend) <li>{{$friend->name }}</li> @endforeach |
5, よく考えたら、問題あり!
user_id → friend_idは、表示出来ているけど、friend_id → user_idも一緒に表示しないとダメでは?(自分のフォローした人しか表示してない。相手からフォローされたリストも表示しないとダメ!)
リレーションを追加
app\User.php
1 2 3 4 5 |
// 自分が含まれている友だちリスト function oppsite_friends() { return $this->belongsToMany('App\User', 'friends', 'friend_id', 'user_id'); } |
//マージして、両方を変数に格納する
HomeController.php
1 2 3 4 5 6 7 8 |
public function index() { // 友達リスト $friends = Auth::User()->friends()->get(); // 自分が友達リストに含まれている人も追加する $friends = $friends->concat(Auth::User()->oppsite_friends()->get()); return view('home', compact('friends')); } |
6, これで完成かな~。と思ったけど、user_id → friend_idとfriend_id → user_idの両方があって重複する場合は、両方表示しちゃダメだな。
mergeだと重複を削除してくれる。concatだと重複のまま存在するみたい
HomeController.php
1 2 3 4 5 6 7 8 |
public function index() { // 友達リスト $friends = Auth::User()->friends()->get(); // 自分が友達リストに含まれている人も追加する(mergeだと重複を削除してくれる。concatだと重複のまま存在する) $friends = $friends->merge(Auth::User()->oppsite_friends()->get()); return view('home', compact('friends')); } |