Система дружбы с Laravel: отношения Many to Many

Я пытаюсь создать систему дружбы с Laravel (я начинаю с нее), но я заблокирован отношениями. Вот что: есть одна таблица «Пользователи» и одна таблица «Друзья», которая содержит следующие столбцы:

friends: id, user_id, friend_id, accepted. 

Он выглядит как «Множество для многих», поэтому вот что я задал для класса User:

 class User extends Eloquent { function friends() { return $this->belongsToMany('User'); } } 

Но когда я пытаюсь:

 $friends = User::find($id)->friends()->get() 

У меня есть эта ошибка:

 Base table or view not found: 1146 Table 'base.user_user' doesn't exist 

Я хотел бы получить список друзей пользователя, не имеет значения, отправил ли пользователь приглашение или получил его. Таким образом, пользователь может установить ba на user_id или на friend_id, а затем я извлекаю данные другого пользователя в зависимости от этого столбца.

Есть идеи? Благодаря!

EDIT: Вот код, который я использую:

 $usersWithFriends = User::with('friendsOfMine', 'friendOf')->get(); $user = User::find(Auth::id())->friends; foreach($user as $item) { echo $item->first()->pivot->accepted; } 

tldr; вам нужно 2 перевернутых отношения, чтобы заставить его работать, проверьте SETUP и ИСПОЛЬЗОВАНИЕ ниже


Во-первых, ошибка – вот как должно выглядеть ваше отношение:

 function friends() { return $this->belongsToMany('User', 'friends', 'user_id', 'friend_id') // if you want to rely on accepted field, then add this: ->wherePivot('accepted', '=', 1); } 

Тогда он будет работать без ошибок:

 $user->friends; // collection of User models, returns the same as: $user->friends()->get(); 

НАСТРОИТЬ

Однако вы хотели бы, чтобы отношение работало в обоих направлениях. Eloquent не обеспечивает такого отношения, поэтому вместо этого вы можете использовать 2 инвертированных отношения и объединить результаты :

 // friendship that I started function friendsOfMine() { return $this->belongsToMany('User', 'friends', 'user_id', 'friend_id') ->wherePivot('accepted', '=', 1) // to filter only accepted ->withPivot('accepted'); // or to fetch accepted value } // friendship that I was invited to function friendOf() { return $this->belongsToMany('User', 'friends', 'friend_id', 'user_id') ->wherePivot('accepted', '=', 1) ->withPivot('accepted'); } // accessor allowing you call $user->friends public function getFriendsAttribute() { if ( ! array_key_exists('friends', $this->relations)) $this->loadFriends(); return $this->getRelation('friends'); } protected function loadFriends() { if ( ! array_key_exists('friends', $this->relations)) { $friends = $this->mergeFriends(); $this->setRelation('friends', $friends); } } protected function mergeFriends() { return $this->friendsOfMine->merge($this->friendOf); } 

ПРИМЕНЕНИЕ

С такой настройкой вы можете сделать это:

 // access all friends $user->friends; // collection of unique User model instances // access friends a user invited $user->friendsOfMine; // collection // access friends that a user was invited by $user->friendOf; // collection // and eager load all friends with 2 queries $usersWithFriends = User::with('friendsOfMine', 'friendOf')->get(); // then $users->first()->friends; // collection // Check the accepted value: $user->friends->first()->pivot->accepted; 

Это, очевидно, проблема в вашей БД, а также определение отношения. Тип отношения «многие ко многим» предполагает использование и промежуточную таблицу. Вот что вам нужно сделать:

  1. Создайте user_friend (id, user_id, fried_id) в вашей схеме.
  2. Удалите ненужные поля из таблиц user и friend .
  3. Создайте соответствующие внешние ключи. user.id -> user_friend.user_id , friend.id -> user_friend.friend_id
  4. Лучше определить полное отношение к моделям пользователя и друга ,

например :

  class User extends Eloquent { function friends() { return $this->belongsToMany('User', 'user_friend', 'user_id', 'friend_id'); } } 

Вы можете читать гораздо больше в документах Laravel, ЗДЕСЬ