laravel 模型关联查询的 belongsToMany 与预加载

belongsToMany

 a表:a_table
 +------+--------+
 | a_id | a_name |
 +------+--------+

 b表:b_table
 +------+--------+
 | b_id | b_name |
 +------+--------+

 中间表:a_b_table
 +------+------+------+
 | id | a_id | b_id |
 +------+------+------+

在a表AModel 中的函数:

public function relateToB(){
    return $this->belongsToMany("App\Models\BModel", "a_b_table", "a_id", "b_id");
}

belongsToMany参数详解:

  1. 第一个参数:a表将要关联的b表模型。
  2. 第二个参数:中间表表名。
  3. 第三个参数:中间表的a表外键。即中间表关联a表所对应的键。
  4. 第四个参数:中间表的b表外键。即中间表关联b表所对应的键。

查询的结果相当于 inner join,而非 left join,同样belongsToMany也会返回重复内容。

预加载

没有预加载的情况:

$all = AModel::all();

foreach($all as $single)  
{  
    single->relateToB(); >> 注意:这里是在调用 relateToB() 函数。
}
  1. find 获取一个 Model 对象 ,即获取一个 id=1 的行,
  2. 再根据这个 Model 对象,调用 relateToB() ,来获取中间表中 a_id=1 对应的 b_id 所对应的 b表 中的行,获取的结果是一个Illuminate\Database\Eloquent\Collection对象。

    Illuminate\Database\Eloquent\Collection对象:
    1、既可以充当数组使用,比如 var c = new \Collection; c[0];
    2、又可以充当查询构造器使用,比如 var c = new \Collection; c->all(); c->where();
    3、该数组对象的元素类型为 BModel
    4、该数组对象的元素类型 BModel 的内容不仅包含 BModel 的全部字段键值对,还包括了一个 pivot 的键,对应的值是一个 Illuminate\Database\Eloquent\Relations\Pivot 类型对象,该对象默认只能包含存在于中间表的键值对。

单次 `single->relateToB();` 返回结果:

=> Illuminate\Database\Eloquent\Collection {#4388
     all: [
       App\Models\BModel {#4403
         b_id:1
         created_at: null,
         updated_at: null,
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4397
           a_id: 1,
           b_id: 4,
           created_at: null,
           updated_at: null,
         },
       },
       App\Models\BModel {#4400
         b_id: 1,
         created_at: null,
         updated_at: null,
         pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4378
           a_id: 1,
           b_id: 5,
           created_at: null,
           updated_at: null,
         },
       },
     ],
   }
总结:

1、先从数据库中的把 a表 全部数据查询出来,再对查询结果挨个进行 relateToB 查询,
2、而 relateToB 查询 是【根据 a表 的结果】,从【数据库的中间表中】分析出数据库中【对应的b表】。
3、也就是向从数据库查询a表后,又要从数据库中循环的查询b表

select * from `posts`
select * from `authors` where `authors`.`id` = ? limit 1 [1]
select * from `authors` where `authors`.`id` = ? limit 1 [1]
select * from `authors` where `authors`.`id` = ? limit 1 [1]

有预加载的情况

$all = AModel::with("relateToB")->get();

foreach($all as $single)  
{  
    single->relateToB; >> 注意:这里是获取键对应的值,并非是函数调用。
}
AModel::with("relateToB")->get() 查询的结果:

=> Illuminate\Database\Eloquent\Collection {#4332
     all: [
       App\Models\AModel {#4334
         a_id: 1,
         created_at: null,
         updated_at: null,
         relateToB: Illuminate\Database\Eloquent\Collection {#4350
           all: [
             App\Models\BModel {#4362
               b_id: 91,
               created_at: null,
               updated_at: null,
               pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4356
                 a_id: 1,
                 b_id: 91,
                 created_at: null,
                 updated_at: null,
               },
             },
             App\Models\BModel {#4368
               b_id: 92,
               created_at: null,
               updated_at: null,
               pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4348
                 a_id: 1,
                 b_id: 92,
                 created_at: null,
                 updated_at: null,
               },
             },
           ],
         },
       },
       App\Models\AModel {#4337
         a_id: 2,
         created_at: null,
         updated_at: null,
         relateToB: Illuminate\Database\Eloquent\Collection {#4333
           all: [],
         },
       },
       App\Models\AModel {#4338
         a_id: 3,
         created_at: null,
         updated_at: null,
         relateToB: Illuminate\Database\Eloquent\Collection {#4175
           all: [
             App\Models\BModel {#4364
               b_id: 94,
               created_at: null,
               updated_at: null,
               pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4352
                 a_id: 3,
                 b_id: 94,
                 created_at: null,
                 updated_at: null,
               },
             },
             App\Models\BModel {#4366
               b_id: 96,
               created_at: null,
               updated_at: null,
               pivot: Illuminate\Database\Eloquent\Relations\Pivot {#4346
                 a_id: 3,
                 b_id: 96,
                 created_at: null,
                 updated_at: null,
               },
             },
           ],
         },
       },
     ],
   }
总结:

1、先从数据库中的把 a表 全部数据查询出来,而该查询结果直接就包含了对应关联的 b表 内容。
2、再从查询结果中直接获取 relateToB 的值
3、也就是向从数据库查询a表后,直接从查询结果继续查询,并不会再向数据库中查询关联表。

select * from `posts`
select * from `authors` where `authors`.`id` in (?, ?, ?, ?, ?) 
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!