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.
There is no
$this
when making static calls. Try replacing$this->scopeDateValid
withself::scopeDateValid
Revised answer
There probably was something else wrong with your code since
$this
is in fact aModel
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.
Analysis
Let's walk through the call stack for executing query scopes:
#10 The
User::scopeValid()
call#8
__callStatic()
handler forModel
From the PHP docs on Method overloading:
Annotated code of
Model.php
's__callStatic()
method (lines 3492-3497):#7
User->valid()
(which doesn't exist)#5
__call
handler forModel
Again, from the PHP docs on Method overloading:
Annotated code of
Model.php
's__call()
method (lines 3474-3483):#2
__call
handler for the queryBuilder
Annotated code of
Builder.php
's__call()
method (lines 933-946):#1
callScope()
method of the queryBuilder
Annotated code of
Builder.php
's__call()
method (lines 825-830):It should work as long as you pass a valid Query object. Maybe typehinting in your function signature will tell you what's wrong?Edit: bernie caught itSlightly off-topic, here is what I like to do to make my code even more readable :)
Another solution for if, for example: You have to call a Date Range on multiple scopes
Usage:
As shown in the docs, you'll want to do your scoping against
$query
, not$this
, and use the scope's magic function rather than calling the internal implementation:As a demonstration, you can see here calling the
testing()
scope applies the logic in thetestingTwo()
scope:So, for your code, this should do the trick: