Scoping to a value
Opened this issue · 0 comments
cyrillkalita commented
@zachleigh - i know about withSetting
.
It is a solid solution, but i do not think it scales very well
What would you say about this approach?
If the model's setting value is default, i do not expect to see a record in property bag.
If it is different from default, a record is in DB.
So:
/**
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $key
* @param mixed $value
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeWhereHasSetting(Builder $query, $key, $value = null): Builder
{
// if the $value matches the default,
// we need to return all models that DO NOT have the key in their property bag
// otherwise, we need to scope DB for records that have it
$default = $query->getModel()->defaultSetting($key);
// matches precisely
if ($default === $value) {
return $query->whereDoesntHave(
'propertyBag',
fn(Builder $builder) => $builder->where('key', $key)
);
}
// first we "cast" the value as array - same way Eloquent will
$value = json_encode(Arr::wrap($value));
// however, for lookup to work, we need to wrap the lookup string in double quotes
return $query->whereHas(
'propertyBag',
fn(Builder $builder) => $builder->where('key', $key)->whereRaw('`value` = ?', json_encode($value))
);
}