zachleigh/laravel-property-bag

Scoping to a value

Opened this issue · 0 comments

@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))
        );
    }