php - Need help writing remove() for global query scope -
here scope, apply()
method works wonderfully.
use illuminate\database\eloquent\scopeinterface; use illuminate\database\eloquent\builder; use illuminate\database\eloquent\model; use carbon\carbon; class jobstatusscope implements scopeinterface { /** * apply scope on query. * * @param \illuminate\database\eloquent\builder $builder * @param \illuminate\database\eloquent\model $model * @return void */ public function apply(builder $builder, model $model) { $builder ->where('active', true) ->wherehas('user', function($q) { $q->where('account_type', 'company') ->wherenested(function($r) { $r->where('stripe_active', true) ->orwherenotnull('subscription_ends_at') ->where('subscription_ends_at', '>', carbon::now()) ->orwherenotnull('trial_ends_at') ->where('trial_ends_at', '>', carbon::today()); }); }); } /** * remove scope query. * * @param \illuminate\database\eloquent\builder $builder * @param \illuminate\database\eloquent\model $model * @return void */ public function remove(builder $builder, model $model) { $query = $builder->getquery(); //dd($query->wheres); $columns = ['stripe_active', 'subscription_ends_at', 'active', 'trial_ends_at']; foreach ((array) $query->wheres $key => $where) { if (in_array($where['column'], $columns)) { unset($query->wheres[$key]); $query->wheres = array_values($query->wheres); } } } }
what tried in remove()
method didn't work.
i have in trait file, , attached model
use app\cable\traits\scopes\jobstatusscope; trait jobstatustrait { public static function bootjobstatustrait() { static::addglobalscope(new jobstatusscope); } /** * query builder without scope applied. * * @return \illuminate\database\eloquent\builder */ public static function withall() { return with(new static)->newquerywithoutscope(new jobstatusscope); } }
when try run mymodel::withall()->get()
should return records without apply()
constraints not.
when dd($query->wheres)
in remove()
method , call ->withall()
this
array:3 [▼ 0 => array:3 [▼ "type" => "null" "column" => "jobs.deleted_at" "boolean" => "and" ] 1 => array:5 [▼ "type" => "basic" "column" => "active" "operator" => "=" "value" => true "boolean" => "and" ] 2 => array:5 [▼ "type" => "basic" "column" => expression {#478 ▼ #value: "(select count(*) `users` `jobs`.`user_id` = `users`.`id` , `account_type` = ? , (`stripe_active` = ? or `subscription_ends_at` not null , `subscription_ends_at` > ? or `trial_ends_at` not null , `trial_ends_at` > ?) , `users`.`deleted_at` null)" } "operator" => ">=" "value" => expression {#476 ▶} "boolean" => "and" ] ]
i can't seem figure out. of laravel quite easy figure out, , "eloquent", escapes me.
any appreciated. thanks!
the wherehas()
restriction works use subquery count of related records.
as can see dd()
output, column
target where
clause not plain string (like 'active'), expression object contains subquery.
you'll need write logic determine if expression 1 matches subquery generated wherehas()
, can remove if is.
a simple example following (n.b. not syntax checked or tested):
public function remove(builder $builder, model $model) { $query = $builder->getquery(); // plain column names $columns = ['active']; // columns present in user relationship subquery $usercolumns = ['stripe_active', 'subscription_ends_at', 'trial_ends_at']; foreach ((array) $query->wheres $key => $where) { // first check if column expression // if not expression, normal check on strings if ($where['column'] instanceof \illuminate\database\query\expression) { // sql value of expression $sql = $where['column']->getvalue(); // see if user columns in sql statement $count = 0; foreach($usercolumns $name) { // increment count if user column found $count += (stripos($sql, $name) !== false) ? 1 : 0; } // if user columns found, assume , remove if ($count == count($usercolumns)) { unset($query->wheres[$key]); $query->wheres = array_values($query->wheres); } } elseif (in_array($where['column'], $columns)) { unset($query->wheres[$key]); $query->wheres = array_values($query->wheres); } } }
you may want come little more strict checking if column names in sql, should started.
Comments
Post a Comment