【问题标题】:Laravel scopes endless loop on eloquent query logLaravel 在 eloquent 查询日志上定义无限循环
【发布时间】:2020-11-08 15:56:19
【问题描述】:

我制作了一个以某种方式以无限循环结束的作用域。在将其简化为最小的可重现示例时,我想到了:

public function apply(Builder $builder, Model $model)
{
    Log::info('[Search] SQL: ' . $builder->toSql() . " Bindings: " . implode(', ', $builder->getBindings()));
}

范围以标准方式在模型中实现:

protected static function booted()
{
    static::addGlobalScope(new AuthorizationScope());
}

如果我像这样运行代码,我最终会遇到以下错误:

已达到“256”的最大函数嵌套级别,正在中止!

为什么无法在范围内获取 SQL 转储?这可以以某种方式修改吗? 在其他地方启用数据库查询日志等选项并不是这个问题的一部分。

【问题讨论】:

  • 在构建 SQL 时是否应用了全局范围?您的 toSql 只是激活了一个递归调用,一次又一次地调用作用域函数。
  • 可能是的。所以我想除非在查询结束,否则没有办法打印出来?
  • 显然。也许深入挖掘 Builder 类。我相信有一个baseQuery 函数,也许它适用于它。 (现在无法检查)。我实际上不确定您要达到的目标。您创建日志是因为您想调查某事,但您想检查什么?

标签: php laravel eloquent scopes laravel-7.x


【解决方案1】:

按照Maarten 的建议深入挖掘,我回答说这确实是一个递归调用。

由于toSql() 不是Eloquent\Builder 方法,而是Query\Builder 方法,它通过__call() 魔术方法被转发,在这种情况下需要获取应用范围before 它实际上执行了作用域:

public function toBase()
{
    return $this->applyScopes()->getQuery();
}

再往下,apply scopes 调用apply() 方法,该方法返回到我的代码,该代码再次触发相同的事情:

if ($scope instanceof Scope) {
    $scope->apply($builder, $this->getModel());
}

所以回答我自己的问题,由于以下原因,不可能做我想做的事。

【讨论】:

    猜你喜欢
    • 2020-10-30
    • 2015-10-20
    • 2017-04-29
    • 2019-06-28
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    相关资源
    最近更新 更多