2013-07-10 1 views
10

я поставил отношения и модели, как показано ниже:Laravel Многие ко многим таблицы самостоятельно ссылающейся работает только один путь

сводной таблицы схемы

Schema::create('friend_user', function(Blueprint $table) { 
    $table->increments('id'); 
    $table->integer('user_id')->unsigned(); 
    $table->integer('friend_id')->unsigned(); 
    $table->timestamps(); 
}); 

сводной таблицы сеялка (это определяет два «дружбу» к которому пользователь «1» принадлежит тот, где пользователь 1 указан в user_id и второй, где пользователь 1 перечислен в другом ид):

$friend_user = array(
     array(
      'id' => 1, 
      'user_id' => 1, 
      'friend_id' => 3, 
     ), 
     array(
      'id' => 2, 
      'user_id' => 4, 
      'friend_id' => 1, 
     ), 

    ); 

модель пользователя

public function friends() 
{ 
return $this->belongsToMany('User', 'friend_user', 'user_id', 'friend_id'); 
} 

Это как предложено Taylor Otwell здесь: https://github.com/laravel/framework/issues/441

Это все работает, но когда я запускаю следующую команду я получаю только один результат:

foreach(Auth::user()->friends as $i) { 
    var_dump($i->id); 
} 

Это возвращает значение «3» но не 4, как ожидалось. Я понимаю, почему это происходит (поскольку user_id не является friend_id), но как я могу получить это, чтобы вернуть коллекцию всех друзей, принадлежащих пользователю (то есть всех дружеских отношений), независимо от того, какой конец соединения (user_id или friend_id) пользователь?

+0

вы onlu имеют 2 отношения в вашей сеялке, один для двух различных пользователей. Таким образом, ваша функция возвращает только один результат для каждого из этих пользователей? – Laurence

+0

Да, но friend_id во второй записи является идентификатором пользователя 1, поэтому обе записи определяют дружбу, просто случается, что один из них был инициирован одним пользователем, а второй - вторым пользователем. Я пытаюсь выяснить, как вернуть дружбу, независимо от того, какой порядок они вводят в систему. –

+0

oh - я понял это сейчас ... возможно, вставьте две записи, когда вы сделаете друга? один для «каждого пути» дружбы? это было бы проще всего. – Laurence

ответ

13

Вместо создания двух записей используется новая функция.

public function friends() 
{ 
    return $this->belongsToMany('User', 'friend_user', 'user_id', 'friend_id'); 
} 

// Same table, self referencing, but change the key order 
public function theFriends() 
{ 
    return $this->belongsToMany('User', 'friend_user', 'friend_id', 'user_id'); 
} 

//You can then call opposite record(s) using: 
foreach(Auth::user()->theFriends as $theFriends) 

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

+0

Для вызова коллекции друзей вы должны звонить друг другу() и theFriends() отдельно. Вряд ли очень хорошее решение, особенно когда вы учитываете двойные SQL-запросы. – Mike

+0

Да, это прекрасно для реализации «последователей», но в меньшей степени для друзей ... –

+3

Отличный пример для самостоятельной привязки отношений «многие ко многим», возможно, имена реализованы немного странно, но основной принцип держится. +1 сэр. –

-2

использование этого

public function friends() 
{ 
return $this->belongsToMany('User', 'friend_user', 'user_id', 'friend_id')->orWhere('friend_id', $this->id);; 
} 

в этом случае вы получите один запрос и одну записи для каждого отношения

+0

Когда вы пытаетесь найти друзей на другой стороне, вы всегда возвращаетесь сами, потому что использует friend_id – cleanunicorn