kodeine / laravel-meta

Fluent Meta Data for Eloquent Models, as if it is a property on your model
MIT License
400 stars 90 forks source link

How to filter via multiple meta values? #84

Closed Temepest74 closed 3 years ago

Temepest74 commented 3 years ago

Ok, i got the idea on how to filter via only one value, but how to do it on two? From docs, this is how you filter on one value:

$post = Post::meta()
    ->where(function($query){
          $query->where('posts_meta.key', '=', 'revision')
                ->where('posts_meta.value', '=', 'draft');
    })
obrunopolo commented 2 years ago

@Temepest74 could you post your solution? I'm struggling to achieve this.

obrunopolo commented 2 years ago

In case someone stumble into this, here is a solution:

 $items = Post::select([
            'posts.*',
            'posts_meta_1.value as meta_1',
            'posts_meta_2.value as meta_2'
        ])
            ->join('posts_meta as posts_meta_1', function ($join) {
                $join->on('posts.id', '=', 'posts_meta_1.post_id')
                    ->where('posts_meta_1.key', '=', 'meta_1');
            })
            ->join('posts_meta as posts_meta_2', function ($join) {
                $join->on('posts.id', '=', 'posts_meta_2.post_id')
                    ->where('posts_meta_2.key', '=', 'meta_2');
            })
            ->where('posts_meta_1.value', '=', 'foo')
            ->where('posts_meta_2.value', '=',  'bar')
            ->get();
Temepest74 commented 2 years ago

This is my solution, but it may work only with my fork of the plugin (I don't remember if I even used what I changed inside the source code).

$this->query->meta('meta')->where(
            static function ($query) use ($validatedData) {
                $query->whereRaw(
                    '
                CASE
                    WHEN `product`.`type` = \'prod_type\'
                    THEN `meta`.`key` = \'product_name_1\'
                    ELSE `meta`.`key` = \'product_name_2\'
                END
                AND `meta`.`value` LIKE ?
            ',
                    ['%' . $validatedData['search_product_name'] . '%']
                );
            }
        )

Your solution looks cleaner so I think I will use it when I got time to refactor the code.