【问题标题】:Extending Eloquent Models with dynamic global scopes使用动态全局范围扩展 Eloquent 模型
【发布时间】:2021-05-19 05:35:25
【问题描述】:

我有一个 MySQL 表,它以 JSON 有效负载接收许多不同的 Jotform 报告。这极大地帮助了快速捕获可查询数据,而不会增加前端开发人员的工作量。

我为表格创建了一个雄辩的模型。我现在希望能够为我们创建的每个 Jotform 创建扩展它的模型。我觉得它会大大提高我的代码的可读性。

我的雄辩模型被称为RawDataReport。它在表中有created_atupdated_atdatareport name 列。我想创建模型ShiftInspectionReport 扩展RawDataReport

我有两份 JotForm 报告,一份名为 Shift Inspection Report,一份名为 Need Inspection Report。两者都是ShiftInspectionReport 模型的一部分。

所以我需要在RawDataReports 表中查询与这些名称匹配的任何报告。我经常需要使用一个或多个报告名称查询 RawDataReports report_name 列。

为了帮助解决这个问题,我创建了一个本地范围来查询接受字符串报告名称或字符串报告名称数组的报告名称。这是RawDataReports 模型的本地作用域。

protected function scopeReportName($query, $report_name): \Illuminate\Database\Eloquent\Builder
{
    if (is_array($report_name)) {
        return $query->orWhere(function ($query) USE ($report_name) {
            ForEach($report_name as $report) {
                if (is_string($report) === false) {
                    throw new \Exception('$report_name must be an array of strings or a string');
                }
    
                $query->where('report_name', $report);
            }
        });
    } else {
        if (is_string($report_name) === false) {
            throw new \Exception('$report_name must be an array of strings or a string');
        }

        return $query->where('report_name', $report_name);
    }
}

编辑 - 在 cmets 之后我简化了 reportName 范围

    protected function scopeReportName($query,array $report_name): \Illuminate\Database\Eloquent\Builder
    {
        return $query->whereIn('report_name',$report_name);
    }

现在在我的ShiftInspectionReport 模型中,我想添加一个可以使用该本地范围并传入$report_name 的全局范围。但是根据这篇文章Laravel 5 Global Scope with Dynamic Parameter,看起来 Laravel 全局作用域不允许你使用动态变量。

我可以在 ShiftInspectionReport 中创建一个本地范围,但可读性看起来像

$reports = ShiftInspectionReport::shiftInspectionReport()->startDate('2021-05-15')->get()

当我真的很想打电话时

ShiftInspectionReport::startDate('2021-05-15')->get()

任何建议或 cmets 将不胜感激。

谢谢

【问题讨论】:

  • 如果startDate(date) 是一个作用域,你可以让它在方法本身中调用shiftInspectionReport() 作用域。 public function scopeStartDate(Builder $query, $date) { return $query->shiftInspectionReport()->....; })
  • 或者,由于shiftInspectionReport() 似乎没有任何参数,您可以将其设为ShiftInspectionReport 模型的全局范围。
  • 顺便说一句,您的scopeReportName() 范围不只是orWhereIn() 吗?
  • 现在你提到它orWhereIn() 听起来好多了,我不明白为什么我不能简化它来使用它。谢谢!你确实解决了我的问题,我现在觉得很傻。我没有意识到在声明全局作用域时我可以只从基类调用局部作用域。我认为是因为在 boot 函数中我无法访问我当时声明的范围。
  • 如果一个类从另一个类扩展而来,它可以访问其所有父类方法

标签: laravel eloquent


【解决方案1】:

感谢 IGP,我发现我可以直接从我的引导函数调用本地范围。

我的扩展类现在看起来像这样,并且可以正常工作。

class ShiftInspection extends RawDataReport
{
    use HasFactory;
    protected static function booted()
    {
        static::addGlobalScope('shift_inspection_report', function(\Illuminate\Database\Eloquent\Builder $builder) {
            $builder->reportName(['Shift Safety Inspection','Need Safety Inspection']);
        });
    }
}

【讨论】:

    猜你喜欢
    • 2014-11-23
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2021-07-21
    相关资源
    最近更新 更多