Laravel开发Tinder克隆项目时with预加载matches关联返回空数组问题
问题原因
- 关联定义中whereIn参数错误:
$this->likesToUsers->keyBy('id')返回的是键为用户ID的模型集合,并非whereIn要求的一维ID数组,条件直接不生效。 - 关联定义不支持预加载:你在
matches关联方法中直接调用了$this->likesToUsers动态属性,当使用with('matches')做预加载时,关联方法会基于空模型实例执行,此时$this->likesToUsers尚未加载数据,永远为空,导致查询条件永远不匹配。 - 中间表名大小写不一致:建表时使用的是全小写名称
users_users_liked,但关联定义中写的是Users_Users_liked,在大小写敏感的操作系统(如Linux)下会直接报找不到表的错误,即使本地Windows环境不报错,上线后也会出问题。
修复方案
- 首先修正所有关联定义中的中间表名称,统一为全小写的
users_users_liked:
public function likesToUsers() { return $this->belongsToMany(self::class, 'users_users_liked', 'user_id', 'user_liked_id'); } public function likesFromUsers() { return $this->belongsToMany(self::class, 'users_users_liked', 'user_liked_id', 'user_id'); }
- 重写
matches关联,使用数据库层面的whereExists查询,无需依赖模型已加载属性,同时支持预加载和延迟加载:
public function matches() { return $this->likesFromUsers() ->whereExists(function ($query) { $query->from('users_users_liked as reverse_likes') // 反向点赞记录的发起者=正向点赞的接收者 ->whereColumn('reverse_likes.user_id', 'users_users_liked.user_liked_id') // 反向点赞的接收者=当前用户ID ->where('reverse_likes.user_liked_id', $this->getKey()); }); }
- (可选优化)Seeder中
attach操作已经会自动写入中间表,不需要额外调用$user->save(),属于冗余代码可以删除。
修复完成后再执行$user = User::with('matches')->findOrFail(1);就能正常返回双向匹配的用户列表了。
内容的提问来源于stack exchange,提问作者gabogabans
相关产品推荐
相关产品推荐

