You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel自定义本地作用域额外参数传递异常问题排查

Laravel自定义作用域突然失效排查

毫无征兆地,Laravel中的自定义作用域突然失效。调用时无法将额外参数与$query参数分离,而是将它们合并为单个数组。

问题案例1:无参数作用域报错

如下简单作用域因报错**"Call to a member function whereNull() on array"**而失效:

// WHERE IS ACTIVE
public function scopeWhereIsActive($query)
{
    return $query->whereNull('show_until')->where('is_old', false)
        ->orWhere('show_until', '>', now())->where('is_old', false)
        ->orderByDesc('created_at');
}

问题案例2:带参数作用域报错

使用带额外参数的自定义作用域时,会出现**"传入1个参数,至少需要2个"**的缺失参数错误,而此前该作用域运行完全正常,且未发现相关变更:

/** WHERE HAS PRODUCT  
 *
 * @param  \Illuminate\Database\Eloquent\Builder  
 * @param  App\Models\Product $product
 * @param  boolean|false $return_with_loaded_products
 * @param  array $included_number_type_sums_array
 * @return void
 */
public function scopeWhereHasProduct($query, $product, $return_with_loaded_products = false, $included_number_type_sums_array = null)
{
    // dd('Order@scopeWherehasProduct parameters', $query, $product, $return_with_loaded_products , $included_number_type_sums_array);

    $query->whereHas('products', function($query) use ($product) {
        $query->where('product_id', $product->id);
    });

    if (isset($included_number_type_sums_array)) {
        foreach ($included_number_type_sums_array as $type) {
            $query->withSum(['products' => function($query) use($product) {
                $query->where('product_id', $product->id);
            }], 'int_orders_products.number_' . $type);
        }
    }

    if ($return_with_loaded_products) {
        $query->with(['products' => function($query) use($product) {
            $query->where('product_id', $product->id);
        }]);
    }

    return $query;
}

核心问题点:callNamedScope参数传递异常

查看Illuminate/Database/Eloquent/Model.php中调用作用域的callNamedScope函数,发现$parameters参数为标准数组,但参数并未被拆分到对应的变量中:

/**
 * Apply the given named scope if possible.
 *
 * @param  string  $scope
 * @param  array  $parameters
 * @return mixed
 */
public function callNamedScope($scope, $parameters = [])
{
    dd('halt',$parameters);
    return $this->{'scope'.ucfirst($scope)}($parameters);
}

调试第一个无参数作用域时,返回结果如下:

^ array:1 [▼
  0 => Illuminate\Database\Eloquent\Builder {#1877 ▼
    #query: Illuminate\Database\Query\Builder {#1864 ▶}
    #model: App\Models\Announcement {#1923 ▶}
    #eagerLoad: []
    #localMacros: []
    #onDelete: null
    #propertyPassthru: array:1 [▶]
    #passthru: array:21 [▶]
    #scopes: []
    #removedScopes: []
  }
]

环境与困惑

  • Laravel版本:9.15.0
  • 未修改Laravel核心代码,回滚操作也无效
  • 不知该从何处排查此问题

内容的提问来源于stack exchange,提问作者Stroomschok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:50:22