在 Laravel 中加入 table 及其模型的默认范围

Join table with its model's default scope in Laravel

目前,我们可以加入 2 个表,例如

    ModelA::join('table_b', 'table_a.id', '=', 'table_b.a_id');

使用这种方法,table_b(即:ModelB)模型的默认范围不会应用于查询。假设 ModelB 现在启用了 SoftDeletes,上面的连接将不包括 whereRaw('table_b.deleted_at IS NULL')。我知道我可以使用以下代码手动添加它。

ModelA::join('table_b', function($join) {
    $join->on('table_a.id', '=', 'table_b.a_id')
    ->whereRaw('table_b.deleted_at IS NULL');
});

我想知道是否有任何方法可以加入,以便它自动应用 ModeB 中的默认范围。类似于:

ModelA::joinModel(ModelB::Class, 'table_a.id', '=', 'table_b.a_id');

Laravel QueryBuilder 在 运行 查询时不考虑 Eloquent 范围。

您可以简单地使用 Eloquent 而不是查询生成器。使用 Eloquent 可以这样实现:

ModelA::with('modelb')->get();

其中 modelbModelA 中定义的 HasMany 关系。

以上语句将产生以下查询:

select * from `modela` where `modelb`.`modela_id` in (1) and `modelb`.`deleted_at` is null

我使用 joinSub() 函数加入子查询。所以下面的代码对我有用:

    ModelA::joinSub(ModelB::select('*'), 'table_b', function($join) {
        $join->on('table_a.id', '=', 'table_b.a_id');
    });

通过使用 joinSub() 我还可以调用 ModelB 上的其他作用域,例如:

    ModelA::joinSub(ModelB::filterThis()->filterThat(), 'table_b', function($join) {
        $join->on('table_a.id', '=', 'table_b.a_id');
    });

过滤掉相关Model的记录,Eloquent方式-

ModelA::with('modelb')->whereHas('modelb', function($query){
      $query->filterThis()->filterThat();
})->get();