$tags = ['a', 'b'];
$posts = Post::whereHas('tags', function($query) use($tags) {
$query->whereIn('name', $tags);
});
Using Where In With An Array http://laravel.com/docs/queries
A ready to test route
Note: you'll need a tags.slug table field for this to work, and specify tags by the comma separated list of slugs in url.
/**
* Sample route to retrieve posts which have
* at least all of the specified, comma separated tags
*/
Route::get('tags/{cstags}', function ($cstags) {
// transform url-provided comma separated tags
$tags = explode(',', $cstags);
array_walk($tags, 'trim');
// we only want "posts" table fields for Eloquent model, thus "selectRaw"
$posts = Post::selectRaw('posts.*')
->join('post_tag', 'post_tag.post_id', '=', 'posts.id')
->join('tags', 'post_tag.tag_id', '=', 'tags.id')
->whereIn('tags.slug', $tags)
->groupBy('posts.id')
->havingRaw('COUNT(posts.id)=?', [count($tags)])
->get();
$output =
'Found ' . $posts->count()
. ' posts having at least all of the ['
. implode(', ', $tags)
. '] tags'
. '<pre>'
. print_r($posts, true)
. '</pre>';
return $output;
});
zenry said:
$tags = ['a', 'b'];
$posts = Post::whereHas('tags', function($query) use($tags) { $query->whereIn('name', $tags); });
Using Where In With An Array http://laravel.com/docs/queries
I tried this way first, but it retrieves posts that have at least one of the given tags, not all.
Then I tried to apply the whereHas
for each tags within a foreach
loop, but it retrieves posts that have only the exact given tags.
marekmurawski said:
A ready to test route
Note: you'll need a tags.slug table field for this to work, and specify tags by the comma separated list of slugs in url.
/** * Sample route to retrieve posts which have * at least all of the specified, comma separated tags */ Route::get('tags/{cstags}', function ($cstags) { // transform url-provided comma separated tags $tags = explode(',', $cstags); array_walk($tags, 'trim'); // we only want "posts" table fields for Eloquent model, thus "selectRaw" $posts = Post::selectRaw('posts.*') ->join('post_tag', 'post_tag.post_id', '=', 'posts.id') ->join('tags', 'post_tag.tag_id', '=', 'tags.id') ->whereIn('tags.slug', $tags) ->groupBy('posts.id') ->havingRaw('COUNT(posts.id)=?', [count($tags)]) ->get(); $output = 'Found ' . $posts->count() . ' posts having at least all of the [' . implode(', ', $tags) . '] tags' . '' . print_r($posts, true) . ''; return $output; });
Although it's not fluent it seems interesting, but I don't get what's a slug and what is it supposed to store ?
Thank you both.
Slug is commonly referenced as a string which can be safely put into URL, essentially it's just a url-friendly representation of a string,
Laravel has a corresponding Str::slug method:
http://laravel.com/api/4.1/Illuminate/Support/Str.html#method_slug
So, you could assume slug == url-friendly name (in your case - url-safe tag name)
I'm aware it's not very neat approach, but as you noted it works. I'd also like to know if it's possible to handle that search more Eloquent way.
Sign in to participate in this thread!
The Laravel portal for problem solving, knowledge sharing and community building.
The community