如何为Laravel关系添加更多条件?

如何为Laravel关系添加更多条件?,laravel,laravel-4,eloquent,relationship,Laravel,Laravel 4,Eloquent,Relationship,我有一个具有以下架构的“连接”表: id requestor_id (user_id) requested_id (user_id) 假设John Doe(请求者)连接到Jane Doe(请求者),Jonnie Doe(请求者)连接到John Doe(请求者)。要列出John Doe的所有关系我必须 inner join "connections" on "users"."id" = "connections"."requested_id" or "users"."id" = "

我有一个具有以下架构的“连接”表:

id 
requestor_id (user_id)
requested_id (user_id)
假设John Doe(请求者)连接到Jane Doe(请求者),Jonnie Doe(请求者)连接到John Doe(请求者)。要列出John Doe的所有关系我必须

inner join "connections" 
  on "users"."id" = "connections"."requested_id" 
  or "users"."id" = "connections"."requestor_id"

但这在Laravel目前是不可能的,因为,好吧,这里没有
belongstomy->or()
方法,所以你怎么做呢?

我已经设法解决了这个关系,并想出了一个临时解决方案:

public function connections()
{
    $relation = $this
        ->belongsToMany(static::class, 'connections', 'requestor_id', 'requested_id')
        ->withTimestamps();

    /// delete the already built inner join
    $relation
        ->getQuery() // Eloquent\Builder
        ->getQuery() // Query\Builder
        ->joins = [];

    /// create a new inner join with the needed or condition
    $relation->getQuery()->getQuery()->join('connections', function($join)
    {
        $join->on('users.id','=','connections.requestor_id');
        $join->orOn('users.id','=','connections.requested_id');
    });

    return $relation;
}

首先,您需要修复该解决方案,因为它不会返回正确的结果(检查下面的)。 第二,它不适用于急切加载,所以我不会使用它

也就是说,您可以创建扩展
belongTomany
的自定义关系,并在模型上调整关系方法,或者使用已有的方法

因此,让我首先提出一些建议,我会找到一个更好的方法(我会使用朋友而不是联系,以便更容易遵循):

现在,它非常易于使用、灵活,并允许快速加载:

$user = User::first();

$user->friends; // merged collection thanks to the accessor

$user->friendOf; // collection of my fans ;)

$user->friendsOfMine; // my idols

$users = User::with('friendOf', 'friendsOfMine')->get();

您的固定解决方案 问题是,仍然会有
where
子句,这将中断您的查询。因此,您需要将其移动到
joinClause
并在那里再添加一个:

public function friends()
{
    $relation = $this
        ->belongsToMany(static::class, 'friends', 'user_id', 'friend_id')
        ->withTimestamps();

    // get underlying Query\Builder
    $query = $relation->getQuery()->getQuery();

    // get rid of wrong where and its bindings
    $query->setBindings([])
    $query->wheres = [];

    // fetch and alter joinClause
    $join = reset($query->joins);
    $join->where('friends.user_id', '=', $this->getKey())
        ->orOn('users.id','=','friends.user_id')
        ->where('friends.friend_id', '=', $this->getKey());


  // Now the join looks like this:
  //
  // $key = $this->getKey();
  //
  // $query->join('friends', function($join) use ($key)
  // {
  //   $join->on('users.id', '=', 'friends.friend_id')
  //       ->where('friends.user_id', '=', $key)
  //      ->orOn('users.id', '=','friends.user_id')
  //       ->where('friends.friend_id', '=', $key);
  // });

    return $relation;   
}
public function friends()
{
    $relation = $this
        ->belongsToMany(static::class, 'friends', 'user_id', 'friend_id')
        ->withTimestamps();

    // get underlying Query\Builder
    $query = $relation->getQuery()->getQuery();

    // get rid of wrong where and its bindings
    $query->setBindings([])
    $query->wheres = [];

    // fetch and alter joinClause
    $join = reset($query->joins);
    $join->where('friends.user_id', '=', $this->getKey())
        ->orOn('users.id','=','friends.user_id')
        ->where('friends.friend_id', '=', $this->getKey());


  // Now the join looks like this:
  //
  // $key = $this->getKey();
  //
  // $query->join('friends', function($join) use ($key)
  // {
  //   $join->on('users.id', '=', 'friends.friend_id')
  //       ->where('friends.user_id', '=', $key)
  //      ->orOn('users.id', '=','friends.user_id')
  //       ->where('friends.friend_id', '=', $key);
  // });

    return $relation;   
}