Laravel Eloquent一对一关联默认查询逻辑是否合理?
Laravel 5.5 Eloquent 一对一关联外键查询逻辑疑惑
我有一个运行Laravel 5.5的项目,数据库包含两张表:
USERS(ID,NAME,PERMISSION_ID)PERMISSIONS(ID,NAME)
我认为用户与权限是一对一关联(用户至少拥有1个且最多1个权限),于是在User模型中定义了如下关联:
class User extends Authenticatable { public function permission () { return $this->hasOne('App\Models\Permission'); } }
但此时Laravel Eloquent会在PERMISSIONS表中查询关联,生成类似如下的SQL:
SELECT * FROM PERMISSIONS WHERE PERMISSIONS.USER_ID = 1
我查阅Laravel文档后得知,可在hasOne方法中指定ForeignKey和LocalKey来解决该关联问题,但我疑惑:Laravel Eloquent默认在PERMISSIONS表中查询是否合理?难道不应该通过USERS表的PERMISSION_ID来查询吗?
问题根源:搞混了hasOne与belongsTo的关联逻辑
其实Laravel Eloquent的关联方法是严格根据外键的存储位置来设计的:
- 当外键存储在关联模型对应的表中时,才用
hasOne/hasMany:比如说如果你的PERMISSIONS表有user_id字段,代表一个用户拥有一个权限,那User模型用hasOne(Permission::class)才是正确的,这时候Eloquent默认去permissions表找user_id匹配当前用户id的记录,也就是你看到的那条SQL的由来,这个默认逻辑是合理的。 - 但你的场景里,外键
permission_id是存在users表中的,这代表用户是「从属」于某个权限的,这种情况下必须用belongsTo来定义关联:
class User extends Authenticatable { public function permission () { return $this->belongsTo('App\Models\Permission'); } }
这样Eloquent就会生成符合你预期的SQL:
SELECT * FROM PERMISSIONS WHERE PERMISSIONS.ID = [当前用户的permission_id]
后续理解与总结
后来我专门研究了hasOne和belongsTo的区别,核心可以概括成:
hasOne:当前模型是「拥有方」,外键在关联表中belongsTo:当前模型是「从属方」,外键在当前模型对应的表中
以后定义关联的时候会特别注意这个逻辑细节,感谢Alexey Mezenin和jedrzej.kurylo的热心解答。
内容的提问来源于stack exchange,提问作者sartoz
相关产品推荐
相关产品推荐

