【问题标题】:Join table with its model's default scope in Laravel在 Laravel 中将表与其模型的默认范围连接起来
【发布时间】:2021-01-18 13:44:41
【问题描述】:

目前,我们可以加入 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-5 eloquent laravel-query-builder


    【解决方案1】:

    我使用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');
        });
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        Laravel QueryBuilder 在运行查询时不考虑 Eloquent 作用域。

        您可以简单地使用 Eloquent 代替 Query Builder。使用 Eloquent 可以这样实现:

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

        其中modelb 是在ModelA 中定义的HasMany 关系。

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

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

        【讨论】:

        • 急加载modelb不会过滤ModelA。它将返回 table_a 和 model_b 中未删除的所有行。我想过滤 table_a 中的行,这些行在 table_d 中没有相关行,其 deleted_at 为空。
        猜你喜欢
        • 2015-01-20
        • 1970-01-01
        • 2019-07-17
        • 1970-01-01
        • 2014-09-04
        • 1970-01-01
        • 1970-01-01
        • 2016-09-09
        • 2017-09-24
        相关资源
        最近更新 更多