原答案
查询范围是静态调用的。
$users = Model::dateValid()->get()
静态调用时没有$this。尝试将$this->scopeDateValid 替换为self::scopeDateValid
修改后的答案
您的代码可能还有其他问题,因为在调用范围时,$this 实际上是 Model 实例。您应该可以使用$query 参数直接调用类作用域方法(就像您所做的那样),或者使用另一个作用域方法解析链作为proposed by ceejayoz。
就个人而言,当您知道要在类上调用作用域方法时,我认为通过整个查询作用域解析过程并没有太大优势,但无论哪种方式都有效。
分析
让我们看一下执行查询范围的调用堆栈:
#0 [internal function]: App\User->scopeValid(Object(Illuminate\Database\Eloquent\Builder))
#1 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(829): call_user_func_array(Array, Array)
#2 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php(940): Illuminate\Database\Eloquent\Builder->callScope('scopeOff', Array)
#3 [internal function]: Illuminate\Database\Eloquent\Builder->__call('valid', Array)
#4 [internal function]: Illuminate\Database\Eloquent\Builder->valid()
#5 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(3482): call_user_func_array(Array, Array)
#6 [internal function]: Illuminate\Database\Eloquent\Model->__call('valid', Array)
#7 [internal function]: App\User->valid()
#8 /vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php(3496): call_user_func_array(Array, Array)
#9 /app/Http/Controllers/UserController.php(22): Illuminate\Database\Eloquent\Model::__callStatic('valid', Array)
#10 /app/Http/Controllers/UserController.php(22): App\User::valid()
#10 User::scopeValid() 通话
#8 __callStatic() Model 的处理程序
来自PHP docs on Method overloading:
公共静态混合__callStatic(字符串$name,数组$arguments)
__callStatic() 在静态上下文中调用不可访问的方法时触发。
Model.php 的 __callStatic() 方法的注释代码(第 3492-3497 行):
public static function __callStatic($method, $parameters)
{
// Uses PHP's late static binding to create a new instance of the
// model class (User in this case)
$instance = new static;
// Call the $method (valid()) on $instance (empty User) with $parameters
return call_user_func_array([$instance, $method], $parameters);
}
#7 User->valid()(不存在)
#5 __call Model 的处理程序
再次,来自PHP docs on Method overloading:
公共混合__call(字符串$name,数组$arguments)
__call() 在对象上下文中调用不可访问的方法时触发。
Model.php 的 __call() 方法的注释代码(第 3474-3483 行):
public function __call($method, $parameters)
{
// increment() and decrement() methods are called on the Model
// instance apparently. I don't know what they do.
if (in_array($method, ['increment', 'decrement'])) {
return call_user_func_array([$this, $method], $parameters);
}
// Create a new \Illuminate\Database\Eloquent\Builder query builder
// initialized with this model (User)
$query = $this->newQuery();
// Call the $method (valid()) on $query with $parameters
return call_user_func_array([$query, $method], $parameters);
}
#2 __call 查询处理程序 Builder
Builder.php 的 __call() 方法的注释代码(第 933-946 行):
public function __call($method, $parameters)
{
if (isset($this->macros[$method])) {
// Handle query builder macros (I don't know about them)
array_unshift($parameters, $this);
return call_user_func_array($this->macros[$method], $parameters);
} elseif (method_exists($this->model, $scope = 'scope'.ucfirst($method))) {
// Now we're getting somewhere! Builds the 'scopeValid' string from
// the original 'valid()' method call. If that method exists on the
// model, use it as a scope.
return $this->callScope($scope, $parameters);
}
// Other stuff for fallback
$result = call_user_func_array([$this->query, $method], $parameters);
return in_array($method, $this->passthru) ? $result : $this;
}
#1 callScope() 查询方法Builder
Builder.php 的 __call() 方法的注释代码(第 825-830 行):
protected function callScope($scope, $parameters)
{
// Add $this (the query) as the first parameter
array_unshift($parameters, $this);
// Call the query $scope method (scopeValid) in the context of an
// empty User model instance with the $parameters.
return call_user_func_array([$this->model, $scope], $parameters) ?: $this;
}