我有两个表:-
A. users table
|--------------------------------------------------------|
| id | fname | lname | deleted |
|--------------------------------------------------------|
| 1 | Jax | Briggs | n |
|--------------------------------------------------------|
| 2 | Juli | Briggs | y |
|--------------------------------------------------------|
| 1 | Nacy | Blew | n |
|--------------------------------------------------------|
B. friend table
|-------------------------------------------------------------|
| id | user_id | receiver_id | status |
|-------------------------------------------------------------|
| 1 | 2 | 3 | 0 |
|-------------------------------------------------------------|
| 2 | 1 | 3 | 1 |
|-------------------------------------------------------------|
| 1 | 2 | 1 | 1 |
|-------------------------------------------------------------|
我正在尝试使用以下查询来检索用户的朋友:-
"SELECT users.id, users.fname, users.lname FROM users,friend
WHERE
IF(friend.user_id != $id, friend.user_id = users.id, friend.receiver_id = users.id)
AND (friend.user_id = $id OR friend.receiver_id = $id)
AND (friend.status = 1)
AND (user.deleted = 'n')"
如果friend.status = 1,则表示接收者已经接受了好友请求。 如果user.deleted = n,则表示该用户帐户尚未删除
如何将上述查询转换为Laravel口才?
我试图做这样的事情:-
$friendshipQuery = Friend::select('users.id', 'users.fname', 'users.lname', 'users.email')
->whereRaw('IF(friend.user_id != ' .$id. ', friend.user_id = users.id, friend.receiver_id = users.id)')
->where(array('friend.status' => Globals::FR_ACCEPTED)) // status which are accepted
->where(function($query) use ($id){
$query->where(array(
'friend.user_id' => $id // check whether user id matches sender id
))
->orWhere(array(
'friend.receiver_id' => $id // check whether user id matches receiver id
));
})
->where('users.deleted', 'n');
不知何故,我无法将两个表连接在一起,因为friend.user_id和friend.receiver_id都引用了users.id。
我该如何实现?
还有其他有效方法吗?
答案 0 :(得分:1)
使用Laravel时,可以使用users
作为数据透视表,作为users
和friends
之间的自引用多对多关系来实现。
如果您使用Laravel模型,请定义一个User
模型和一个public function friends()
关系,具体程度如下:
class User extends Model {
...
public function friends(){
return $this->belongsToMany(User::class, "friends", "user_id", "receiver_id");
}
}
然后,您将可以简单地进行以下操作:
$user = User::with(["friends"])->first();
$friends = $user->friends;
dd($user, $friends);
如果您需要过滤该查询以仅显示接受的朋友,则只需执行以下操作:
$user = User::with(["friends" => function($query){
$query->where("status", "=", Globals::FR_ACCEPTED);
}])->first();
$friends = $user->friends;
dd($user, $friends);
您甚至可以将status
检查添加到关系的末尾,以便仅返回接受的朋友。但是,无论哪种方式,Laravel都提供了一些强大的工具来有效地处理此问题,因此请考虑使用它们。
https://laravel.com/docs/5.7/eloquent-relationships#many-to-many
答案 1 :(得分:0)
好吧,我将使用... join()并为表名加上别名以避免混淆(用户u
,朋友f
,用户朋友uf
) )
$friendshipQuery = Friend::table('users as u')
->join('friend as f', 'f.user_id', '=', 'u.id')
->join('users as uf', 'f.receiver_id', '=', 'uf.id')
->select('uf.*')
->where('f.status', '1')
->where('uf.deleted', 'n')
->where('u.deleted', 'n')
->where(function($query) use ($id)
{
$query->where(array('friend.user_id' => $id))
->orWhere(array('friend.receiver_id' => $id));
});
顺便说一句,笛卡尔联接是可怕且不赞成的
我会用这种方式重写SQL查询
SELECT uf.id, uf.fname, uf.lname
FROM users u
LEFT JOIN friend f ON u.id = f.user_id
LEFT JOIN users uf ON uf.id = f.receiver_id
WHERE (f.user_id = $id OR f.receiver_id = $id)
AND (f.status = 1)
AND (uf.deleted = 'n')
AND (u.deleted = 'n')