我将如何在 Laravel Eloquent 中编写这个 MySQL 查询?

Posted

技术标签:

【中文标题】我将如何在 Laravel Eloquent 中编写这个 MySQL 查询?【英文标题】:How would I code this MySQL query in Laravel Eloquent? 【发布时间】:2015-10-19 10:42:34 【问题描述】:

我正在尝试使用半复杂的查询(无论如何按照我的标准),但我想不出如何使用查询生成器或使用 eloquent 关系来完成。

我的关系表是:user_id_1 | user_id_2 | status | action_user_id在朋友的情况下,action_user_id可以忽略,status = 1。每个关系只有一行,因此如果要选择属于用户 17 的所有关系,则需要同时检查 user_id_1 和 user_id_2,因为 id 可能位于任一列中。我从这里遵循了数据库结构:http://www.codedodle.com/2015/03/social-network-friends-relationship.html

我尝试执行的查询类型是:

SELECT users.*
FROM users
LEFT JOIN users_relationships AS r
    ON (
        users.id = r.user_id_1
        AND r.user_id_1 != $user_id
    ) OR (
        users.id = r.user_id_2
        AND r.user_id_2 != $user_id
    )
WHERE r.status = 1
    AND (
        r.user_id_1 = $user_id
        OR r.user_id_2 = $user_id
    )

这样的事情在雄辩的关系中是最好的,所以它很容易执行:$user->friends 它会返回上面的结果,但我在各个方向都被困住了。

不幸的是,我最好的尝试是没有使用关系:

User::with('profile')->join('user_relationships as r', function($join) use ($user_id) 
    $join->on(DB::raw('( users.id = r.user_id_1 AND r.user_id_1 != ? )', [$user_id]), DB::raw(''), DB::raw(''));
    $join->orOn(DB::raw('( users.id = r.user_id_2 AND r.user_id_2 != ? )', [$user_id]), DB::raw(''), DB::raw(''));
)
->where('r.status', 1)
->where(function($query) use ($user_id) 
    $query->where('r.user_id_1', $user_id)
        ->orWhere('r.user_id_2', $user_id);
)
->get(['users.*']);

然而,这给了我与参数相关的错误:

SQLSTATE[HY093]: Invalid parameter number (SQL: select `users`.* from `users` inner join `user_relationships` as `r` on ( users.id = r.user_id_1 AND r.user_id_1 != 1 ) or ( users.id = r.user_id_2 AND r.user_id_2 != 30 ) where `users`.`deleted_at` is null and `r`.`status` = 30 and (`r`.`user_id_1` = ? or `r`.`user_id_2` = ?))

我不知道如何去做我想做的事。

【问题讨论】:

【参考方案1】:

问题出在这里:

DB::raw('( users.id = r.user_id_1 AND r.user_id_1 != ? )', [$user_id])

DB::raw() 不接受绑定的第二个参数。请改用->on()->where()(感谢user4621032):

->leftJoin('users_relationships AS r', function($join) use($user_id) 
    $join->on('users.id','=','r.users_id_1')->where('r.users_id_1','!=',$user_id)
         ->orOn('users_id','=','r.users_id_2')->where('r.users_id_2','!=',$user_id);
)

所以要根据需要设置您的->friends() 函数,您可以使用:

public function friends()

    $user_id = $this->id;
    return self::with('profile')
        ->leftJoin('users_relationships AS r', function($join) use($user_id) 
            $join->on('users.id','=','r.users_id_1')->where('r.users_id_1','!=',$user_id)
                 ->orOn('users_id','=','r.users_id_2')->where('r.users_id_2','!=',$user_id);
        )
        ->where('r.status', 1)
        ->where(function($query) use ($user_id) 
            $query->where('r.user_id_1', $user_id)
            ->orWhere('r.user_id_2', $user_id);
        )
        ->get(['users.*']);

【讨论】:

是否可以通过雄辩的关系做到这一点?如果不是,这不是一个大问题,但很高兴发现。 :) 我已经更新了一些示例代码——这是我在这种复杂的连接情况下能做的最好的事情。 我明白了。谢谢!【参考方案2】:

可能是这样的

 DB::table('users')
            ->leftJoin('users_relationships AS r', function($join) use($user_id)
                $join->on('users.id','=','r.users_id_1')->where('r.users_id_1','!=',$user_id)
                ->orOn('users_id','=','r.users_id_2')->where('r.users_id_2','!=',$user_id);
            )
              ->where('r.status',1)
              ->where('r.user_id_1','=',$user_id)
              ->orWhere('r.user_id_2','=',$user_id)
              ->get();

【讨论】:

不错!我从来没有在$join 闭包上使用过->where,忘了它在那里。 我希望你不介意我已经更新了接受的答案以使用这个更好的解决方案。 @Ben 很高兴它有帮助

以上是关于我将如何在 Laravel Eloquent 中编写这个 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

带有 Eloquent 的 Laravel 不会在数据库中保存模型属性

laravel Eloquent ORM 多表插入

Laravel 带计数的多重连接(不是 Eloquent)

Laravel Eloquent 显示后更新

在 Laravel 中使用 Eloquent 多态关系对数据进行分类

如何在 Laravel/Eloquent 中获得完整的关系