php - Can you make a scope in laravel that calls various other scopes? -
i have model in laravel has various scopes defined. want use of them in lot of places rather chaining them i'd rather able call 1 scope calls of other scopes 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 work though, there way achieve this?
original answer
query scopes called statically.
$users = model::datevalid()->get()
there no $this
when making static calls. try replacing $this->scopedatevalid
self::scopedatevalid
revised answer
there else wrong code since $this
in fact model
instance when scopes called. should able either call class scope methods directly $query
parameter (like did) or use chain of scope method resolution proposed ceejayoz.
personally, don't see of advantage in going through whole query scope resolution process when know want call scope methods on class, either way works.
analysis
let's walk through call stack 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()
call
#8 __callstatic()
handler model
from php docs on method overloading:
public static mixed __callstatic ( string $name , array $arguments )
__callstatic() triggered when invoking inaccessible methods in static context.
annotated code of model.php
's __callstatic()
method (lines 3492-3497):
public static function __callstatic($method, $parameters) { // uses php's late static binding create new instance of // model class (user in case) $instance = new static; // call $method (valid()) on $instance (empty user) $parameters return call_user_func_array([$instance, $method], $parameters); }
#7 user->valid()
(which doesn't exist)
#5 __call
handler model
again, php docs on method overloading:
public mixed __call ( string $name , array $arguments )
__call() triggered when invoking inaccessible methods in object context.
annotated code of model.php
's __call()
method (lines 3474-3483):
public function __call($method, $parameters) { // increment() , decrement() methods called on model // instance apparently. don't know do. if (in_array($method, ['increment', 'decrement'])) { return call_user_func_array([$this, $method], $parameters); } // create new \illuminate\database\eloquent\builder query builder // initialized model (user) $query = $this->newquery(); // call $method (valid()) on $query $parameters return call_user_func_array([$query, $method], $parameters); }
#2 __call
handler 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 them) array_unshift($parameters, $this); return call_user_func_array($this->macros[$method], $parameters); } elseif (method_exists($this->model, $scope = 'scope'.ucfirst($method))) { // we're getting somewhere! builds 'scopevalid' string // original 'valid()' method call. if method exists on // model, use scope. return $this->callscope($scope, $parameters); } // other stuff fallback $result = call_user_func_array([$this->query, $method], $parameters); return in_array($method, $this->passthru) ? $result : $this; }
#1 callscope()
method of query builder
annotated code of builder.php
's __call()
method (lines 825-830):
protected function callscope($scope, $parameters) { // add $this (the query) first parameter array_unshift($parameters, $this); // call query $scope method (scopevalid) in context of // empty user model instance $parameters. return call_user_func_array([$this->model, $scope], $parameters) ?: $this; }
Comments
Post a Comment