问题描述
我在Laravel中有一个定义了各种范围的模型.我想在很多地方都使用它们,而不是将它们链接在一起,我只想能够像这样调用一个作用域,并调用所有其他作用域:
I have a model in Laravel that has various scopes defined. I want to use all of them in a lot of places so rather than chaining them together I'd rather just be able to call one scope that calls all of the other scopes like so:
function scopeValid($query, $user_id) {
$query = $this->scopeDateValid($query);
$query = $this->scopeMaxUsesValid($query);
$query = $this->scopeCustomerMaxUsesValid($query, $user_id);
return $query;
}
这似乎不起作用,有没有办法实现这一目标?
This doesn't seem to work though, is there a way to achieve this?
推荐答案
原始答案
查询范围是静态调用的.
Original answer
Query scopes are called statically.
$users = Model::dateValid()->get()
进行静态调用时没有$this
.尝试将$this->scopeDateValid
替换为self::scopeDateValid
There is no $this
when making static calls. Try replacing $this->scopeDateValid
with self::scopeDateValid
您的代码可能存在其他问题,因为在调用作用域时,$this
实际上是Model
实例.您应该能够直接使用$query
参数调用类作用域方法(就像您所做的那样),或者使用另一个作用域方法解析链作为.
There probably was something else wrong with your code since $this
is in fact a Model
instance when scopes are called. You should be able to either call the class scope methods directly with the $query
parameter (like you did) or use another chain of scope method resolution as proposed by ceejayoz.
就个人而言,当您知道要在类上调用范围方法时,在整个查询范围解析过程中看不出太多优势,但是无论哪种方法都可以.
Personally, I don't see much of an advantage in going through the whole query scope resolution process when you know you want to call the scope methods on your class, but either way works.
让我们遍历用于执行查询范围的调用堆栈:
Let's walk through the call stack for executing query scopes:
#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文档 :
#10 The User::scopeValid()
call
#8 __callStatic()
handler for Model
From the PHP docs on Method overloading:
__ callStatic().
__callStatic() is triggered when invoking inaccessible methods in a static context.
Model.php
的__callStatic()
方法的注释代码(行3492-3497):
Annotated code of Model.php
's __callStatic()
method (lines 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()
(不存在)
$this
的#5 __call
处理程序
再次从有关方法重载的PHP文档:
#7 User->valid()
(which doesn't exist)
#5 __call
handler for Model
Again, from the PHP docs on Method overloading:
__ call().
__call() is triggered when invoking inaccessible methods in an object context.
Model.php
的__call()
方法的注释代码(第3474-3483行):
Annotated code of Model.php
's __call()
method (lines 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行):
#2 __call
handler for the query Builder
Annotated code of Builder.php
's __call()
method (lines 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行):
#1 callScope()
method of the query Builder
Annotated code of Builder.php
's __call()
method (lines 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;
}
这篇关于您可以在laravel中创建一个可以调用其他各种作用域的作用域吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!