2013-07-10 50 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在朋友id是列出的第二個):

$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'); 
} 

這是作爲建議由泰勒Otwell這裏:https://github.com/laravel/framework/issues/441

這一切工作,但是當我運行以下命令我得到的結果只有一個:

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

這將返回值「3」但不像預期的那樣。我明白爲什麼會發生這種情況(因爲user_id不是friend_id),但我怎麼能得到這個返回屬於用戶的所有朋友(即所有友誼)的集合,而不管連接的哪一端(user_id或friend_id)爲用戶是?

+0

你onlu在你的播種機2間的關係,一個是兩個不同的用戶。所以你的函數只會爲每個用戶返回一個結果? – Laurence

+0

是的,但第二個記錄上的friend_id是用戶1的id,因此兩個條目都定義了友誼,只是發生了一個由一個用戶發起,另一個由第二個用戶發起。我試圖找出如何返回友誼,而不管他們進入系統的順序如何。 –

+0

哦 - 我現在明白了......當你結交朋友時可能插入兩條記錄?一個用於友誼的「每條路」?這將是最簡單的。 – 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

這需要分別調用friends()和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