发现 ORM 方法 MorphToMany 的一个 Bug
person 表 | |
---|---|
id | integer |
name | string |
address_rel 表 | |
---|---|
id | integer |
lsc | integer (11 or 101) 此处在 MorphMap 定义映射关系 |
lid | integer |
address | integer |
address 表 | |
---|---|
id | integer |
country | integer 国家 ID |
province | integer 省 ID |
city | integer 市区 ID |
….. | 省略 |
首先,在 AppServiceProvider 我定义了 morphMap:
Relation::morphMap([
'11' => Person::class,
'101' => Company::class,
]);
然后,在 Person 模型中,定义了获取所有地址的方法:
public function address()
{
return $this->morphToMany(
Address::class, //地址表
'lsc', //多态关联表中的映射表关系
'address_rel', //多态关联表
'lid', //映射表ID
'address' //地址ID
);
}
最后,在 Controller 层,来获取 Person 的所有地址:
$person = Person::find(1);
$person->address->toArray();
此时报错信息为:
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'lu_address_rel.lsc_type' in 'field list' (SQL: select `lu_address`.*, `lu_address_rel`.`lid` as `pivot_lid`, `lu_address_rel`.`address` as `pivot_address`, `lu_address_rel`.`lsc_type` as `pivot_lsc_type` from `lu_address` inner join `lu_address_rel` on `lu_address`.`id` = `lu_address_rel`.`address` where `lu_address_rel`.`lid` = 56 and `lu_address_rel`.`lsc_type` = 11)"
通过上面可以看到,我们传的 lsc 在 Laravel 中自动拼上了 _type,而 lid 是正确的,这时我们通过追查源码发现
如上图所示,在我们传入 $foreignPivotKey 字段时,Laravel 做了相应的判断处理,如果传了这个字段(也就是 lid),则完全使用用户传入的值,否则将拼接为 $name . ‘_id’ ,这里的 $name 就是我们在 Model 中传入的第二个参数
那么我们接着来看 $name 参数是如何处理的
追查到这里发现,Laravel 是直接将用户传入的 $name 参数拼上了 _type ,这就出现了上面的报错信息。
通过以上信息发现我们如果要用到 MorphToMany 方法,就必须要把表设计改为 Laravel 的规范,否则,目前的 Laravel 版本中用 MorphToMany 是完成不了需求的。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: