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
相关产品推荐
相关产品推荐

