Yii2中通过viaTable关联查询用户回复的方法是否正确
问题结论
你写的这个关联方法不正确,有3处核心逻辑错误,跑起来要么报字段不存在的SQL错误,要么查出来的结果完全不符合预期。
具体错误点
viaTable的关联映射逻辑写反
Yii2中viaTable方法的第二个参数格式是[中间表字段名 => 当前主模型(Users)对应字段名],作用是把主模型的字段和中间表的关联字段做匹配。你现在写的['replies_id' => 'id']是拿用户id去匹配中间表的回复id字段,完全对应不上关联关系。hasMany的外键映射错误hasMany的第二个参数格式是[关联模型(Replies)字段名 => 中间表/直接关联表对应字段名],你现在写的['user_id' => 'id']是拿中间表的主键id去匹配回复表的发布者user_id字段,本质是查「id和回复发布者id一致的内容」,完全不是你要的通过中间表关联回复的逻辑。- 筛选条件挂载位置错误
你写的['entity'=>'user']是中间表replies_links的多态类型标记字段,不是回复表replies的字段,直接挂在链式调用最后,生成的SQL会去找replies.entity字段,直接抛出字段不存在的异常。
正确实现代码
首先你要确认中间表replies_links的字段设计:按你用的多态关联逻辑,中间表一般有三个核心关联字段:
replies_id:关联回复表replies的主键identity:标记关联的实体类型,值为user时代表关联用户实体- 关联实体id字段:存对应实体的主键id,一般命名为
entity_id,如果你的表用了别的命名(比如user_id、target_id)替换成实际字段名即可。
对应正确的方法代码如下:
public function getAllRepliesForUsers() { return $this->hasMany(Replies::class, ['id' => 'replies_id']) ->viaTable('replies_links', ['entity_id' => 'id'], function($query) { // 中间表的筛选条件要写在viaTable的回调中,才会作用在中间表查询上 $query->where(['entity' => 'user']); }); }
关联逻辑说明
上述代码生成的查询链路完全符合你的需求:
- 拿到当前Users模型的主键id
- 去中间表
replies_links查询entity = 'user'且entity_id = 当前用户id的记录,取出所有关联的replies_id - 去回复表
replies中查询主键id在上述replies_id集合中的所有记录,就是当前用户关联的所有回复。
补充:如果你的需求是查询「当前用户自己发布的所有回复」,根本不需要走中间表,直接写
return $this->hasMany(Replies::class, ['user_id' => 'id']);即可,不需要调用viaTable。
内容的提问来源于stack exchange,提问作者user17045604
相关产品推荐
相关产品推荐

