与Laravel的友谊系统:多对多的关系

Cod*_*del 19 php eloquent laravel-4

我正在尝试用Laravel创建一个友谊系统(我从它开始),但我被关系阻挡了.事情就是这样:有一个表用户和一个表友,其中包含以下列:

friends: id, user_id, friend_id, accepted.
Run Code Online (Sandbox Code Playgroud)

它看起来像一个多对多,所以这是我在User类上设置的:

class User extends Eloquent {
    function friends()
    {
        return $this->belongsToMany('User');
    }
}
Run Code Online (Sandbox Code Playgroud)

但是当我尝试:

$friends = User::find($id)->friends()->get()
Run Code Online (Sandbox Code Playgroud)

我有这个错误:

Base table or view not found: 1146 Table 'base.user_user' doesn't exist
Run Code Online (Sandbox Code Playgroud)

我想获得一个用户朋友列表,无论用户是发送了邀请还是收到了邀请.因此,用户可以在user_id或friend_id上进行操作,然后根据该列检索其他用户的数据.

任何的想法?谢谢!

编辑:这是我使用的代码:

$usersWithFriends = User::with('friendsOfMine', 'friendOf')->get();
$user = User::find(Auth::id())->friends;

foreach($user as $item) {
    echo $item->first()->pivot->accepted;
} 
Run Code Online (Sandbox Code Playgroud)

Jar*_*zyk 49

tldr; 你需要2个反向关系来使其工作,检查下面的SETUP和USAGE


首先是错误 - 这就是你的关系应该是这样的:

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);
}
Run Code Online (Sandbox Code Playgroud)

然后它将正常工作:

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

建立

但是,您希望关系以两种方式工作.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);
}
Run Code Online (Sandbox Code Playgroud)

用法

通过这样的设置,您可以这样做:

// 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;
Run Code Online (Sandbox Code Playgroud)

  • 请让我们知道如何分页?$user->friends()->paginate(25) 将不起作用。 (2认同)

Vit*_*Kos 5

显然,这是数据库中的一个问题,也是关系的定义。多对多关系类型期望您使用和中间表。这是您要做的:

  1. user_friend (id, user_id, fried_id)在您的架构中创建一个表。
  2. userfriend表中删除不必要的字段。
  3. 创建适当的外键。user.id-> user_friend.user_idfriend.id->user_friend.friend_id
  4. 更好地在UserFriend模型上定义完整关系,

例如 :

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

您可以在Laravel文档阅读等等,这里

  • OP仅具有一个名为“ User”的表,没有“ Friend”表。 (2认同)