hasOneThrough 改进支持 "belongsToThrough"(假设这样叫吧)

浏览:1147 发布日期:2022/05/26
hasOneThrough('关联模型', '中间模型', '外键', '中间表关联键','当前模型主键','中间模型主键');

官方给的案例是 User hasOne Profile Profile hasOne Card
User和Cart没有直接关联关系 通过中间模型Profile 可以在 User里面获取 Card。

很多时候估计使需要 Card里面获取User 参数就需要改下顺序才支持:
Card里面:
$this->hasOneThrough(User::class,Profile::class,'Profile.id','User.id','Card.profile_id','Profile.user_id');
$this->hasOneThrough(User::class,Profile::class,'中间表Profile主键','远程关联表User主键','Card关联Profile的关联字段','Profile关联User的关联字段');

这种情况我们估计也需要:
User hasMany Order(一个人有很多订单 Order belongsTo User) Order hasMany OrderItem(一个订单有多个订单项(产品) OrderItem belongsTo Order )
User 和 OrderItem 无直接关联 (你希望简单点,当然可以考虑下订单生成订单项的时候 OrderItem里面备份下user_id 让 OrderItem 直接关联到User 这里不去考虑这样做)

现在希望在 OrderItem里面获取User:
$this->hasOneThrough(User::class,Order::class,'id','id','order_id','user_id');


不过当一个人有多个订单以后,部分关联会丢失,需要修改Orm源码支持:

orm/model/relation/hasOneThrough 下 eagerlyWhere方法 大概 153行开始:// 组装模型数据
        $data = [];
        /*
        // TP 这里是原本的代码
        // array_flip会造成 针对 "belongsToThough" 一些关联丢失
        $keys = array_flip($keys);

        foreach ($list as $set) {
            $data[$keys[$set->{$this->throughKey}]] = $set;
        }
        */
        // 调整的代码
        foreach ($list as $set) {
            foreach ($keys as $key => $value) {
                if ($value == $set->{$this->throughKey}) {
                    unset($keys[$key]);
                    $data[$key] = $set;
                }
            }
        }
        return $data;
最后,上面的情况都可以不用远程关联,关联再关联也可以实现。
评论(
后面还有条评论,点击查看>>