Laravel中belongsTo关联含双外键的好友查询问题
解决Laravel Chat模型动态关联好友的问题
看起来你已经搭好了基础的关联关系,只差一步动态判断当前用户的逻辑就搞定了。因为聊天记录里的user_id和friend_id是双向的——当前登录用户可能是发起聊天的人,也可能是被添加的好友,所以得根据Auth::id()来动态关联对应的用户模型。
我给你两种实用的解决方案,你可以根据需求选:
方案一:使用访问器(推荐)
这种方式最直观,给Chat模型加个访问器,自动返回当前用户对应的好友:
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Auth; class Chat extends Model { protected $fillable = ['user_id', 'friend_id']; // 关联聊天发起者(user_id对应User) public function userOne() { return $this->belongsTo(User::class, 'user_id'); } // 关联聊天好友(friend_id对应User) public function userTwo() { return $this->belongsTo(User::class, 'friend_id'); } // 动态获取当前用户的好友 public function getFriendAttribute() { $currentUserId = Auth::id(); // 用户未登录直接返回null if (!$currentUserId) { return null; } // 判断当前用户身份,返回对应关联模型 if ($this->user_id === $currentUserId) { return $this->userTwo; } elseif ($this->friend_id === $currentUserId) { return $this->userOne; } // 当前用户不在这条聊天记录里时返回null return null; } }
使用方式:
获取单条聊天记录时,直接访问friend属性就能拿到好友模型:
$chat = Chat::find(1); echo $chat->friend->name; // 输出好友名称
批量查询时,记得预加载userOne和userTwo,避免N+1查询问题:
$chats = Chat::with(['userOne', 'userTwo'])->get(); foreach ($chats as $chat) { if ($chat->friend) { echo $chat->friend->name; } }
方案二:添加查询范围(批量查询更高效)
如果需要批量获取当前用户参与的聊天记录并直接关联好友,可以加个查询范围,在数据库层面完成判断:
// 在Chat模型中添加以下方法 public function scopeWithFriend($query) { $currentUserId = Auth::id(); return $query->addSelect([ 'friend_id' => User::select('id') ->whereRaw('users.id = CASE WHEN chats.user_id = ? THEN chats.friend_id ELSE chats.user_id END', [$currentUserId]) ])->with(['userOne', 'userTwo']); } // 再加一个筛选当前用户聊天记录的范围 public function scopeForCurrentUser($query) { $currentUserId = Auth::id(); return $query->where('user_id', $currentUserId)->orWhere('friend_id', $currentUserId); }
使用方式:
// 获取当前用户的所有聊天记录,并自动关联好友 $chats = Chat::forCurrentUser()->withFriend()->get(); foreach ($chats as $chat) { echo $chat->friend->name; }
补充说明
你之前定义的userOne和userTwo关联是完全正确的,问题就出在没写完的friend方法里——只要加入对当前用户ID的判断,就能动态返回对应的好友模型啦。
内容的提问来源于stack exchange,提问作者null
相关产品推荐
相关产品推荐

