使用WhereHas

时间:2016-12-12 13:08:42

标签: php mysql laravel model eloquent

一点背景......

我的User模型有以下两种关系:

/**
 * Get the connections added by the user.
 *
 * @param boolean $accepted
 * @return BelongsToMany
 */
public function addedConnections($accepted = true)
{
    return $this->belongsToMany('App\Models\User\User', 'user_connections', 'user_id', 'connection_id')
        ->wherePivot('connection_type', '=', 'user')
        ->wherePivot('accepted', '=', $accepted)
        ->withTimestamps();
}

/**
 * Get the connections the user was invited to.
 *
 * @param boolean $accepted
 * @return BelongsToMany
 */
public function invitedConnections($accepted = true)
{
    return $this->belongsToMany('App\Models\User\User', 'user_connections', 'connection_id', 'user_id')
        ->wherePivot('connection_type', '=', 'user')
        ->wherePivot('accepted', '=', $accepted)
        ->withTimestamps();
}

我试图编写一个合并上述两种方法的方法来返回connections。但是,我不想将其作为Laravel Collection返回,而是将其作为查询Builder返回,以便我可以添加到查询...

这就是我实施的内容:

/**
 * Get the connections the user was invited to.
 *
 * @return Builder
 */
public function connections()
{
    return $this
        ->where(function ($query) {
            $query
                ->whereHas('addedConnections')
                ->orWhereHas('invitedConnections');
        })
        ->whereDoesntHave('blocked');
}

问题......

这个函数的问题在于它没有正确构建查询(从我所看到的)。它不是返回当前用户的连接,而是返回所有连接。这是因为查询中有以下两行:

WHERE  user_connections.user_id = users.id
WHERE  user_connections.connection_id = users.id

users.id应该是当前用户的ID,而不是对users表的引用。

我的问题

  1. 为什么会这样?为什么模型id(1,2,3等)没有插入到查询中而不是对表的引用?
  2. 无论是什么导致问题,我都很想知道是否有更好的方法来实现上述目标?
  3. 更新1

    我想我可能已经解决了以下问题:

    /**
     * Get the connections the user was invited to.
     *
     * @return Builder
     */
    public function connections()
    {
        return $this
            ->where(function ($query) {
                $query
                    ->whereHas('addedConnections', function ($query) {
                        $query->where('id', '=', $this->id);
                    })
                    ->orWhereHas('invitedConnections', function ($query) {
                        $query->where('id', '=', $this->id);
                    });
            })
            ->whereDoesntHave('blocked');
    }
    

    这是正确的解决方案吗?

    其他信息

    如果需要,这是完整的SQL查询:

    SELECT
       * 
    FROM
       `users` 
    WHERE
       (
          EXISTS 
          (
             SELECT
                * 
             FROM
                `users` AS `laravel_reserved_3` 
                INNER JOIN
                   `user_connections` 
                   ON `laravel_reserved_3`.`id` = `user_connections`.`connection_id` 
             WHERE
                `user_connections`.`user_id` = `users`.`id` -- THIS IS THE ISSUE
                AND `user_connections`.`connection_type` = 'user' 
                AND `user_connections`.`accepted` = TRUE 
                AND `laravel_reserved_3`.`deleted_at` IS NULL
          )
          OR EXISTS 
          (
             SELECT
                * 
             FROM
                `users` AS `laravel_reserved_4` 
                INNER JOIN
                   `user_connections` 
                   ON `laravel_reserved_4`.`id` = `user_connections`.`user_id` 
             WHERE
                `user_connections`.`connection_id` = `users`.`id`  -- THIS IS THE ISSUE
                AND `user_connections`.`connection_type` = 'user' 
                AND `user_connections`.`accepted` = TRUE 
                AND `laravel_reserved_4`.`deleted_at` IS NULL
          )
       )
       AND NOT EXISTS 
       (
          SELECT
             * 
          FROM
             `users` AS `laravel_reserved_5` 
             INNER JOIN
                `user_blocks` 
                ON `laravel_reserved_5`.`id` = `user_blocks`.`blocked_id` 
          WHERE
             `user_blocks`.`user_id` = `users`.`id` 
             AND `laravel_reserved_5`.`deleted_at` IS NULL
       )
       AND `users`.`deleted_at` IS NULL
    

0 个答案:

没有答案