Reputation: 129
In October CMS how to filter blog posts with multiple categories? I'm using RainLab Blog plugin. The plugin only allows filtering with one category. I want a combined result. Please help.
Upvotes: 2
Views: 2541
Reputation: 428
First solution:
In the Code tab of the CMS page:
use RainLab\Blog\Models\Post as BlogPost;
function onStart(){
$this['filteredPosts'] = BlogPost::whereHas('categories', function($q) {
$q->whereIn('slug', ['cat-a','cat-b']);
})->get();
}
Second solution:
In the October CMS backend you can't configure the categoryFilter property of the BlogPosts component with a list of categories. But you can let this property empty for including all categories, and then you can use the exceptCategories property with the list of categories you don't want. exceptCategories admit a comma separated list of category slugs or variable with such a list of categories you want to exclude.
[blogPosts blogPostsCatACatB]
...
exceptCategories = "cat-c, cat-d, cat-e"
Upvotes: 3
Reputation: 2641
You will need to use some custom code to filter based on multiple categories. If still using the PostList component, make the following changes and you will be able to filter the list based on multiple categories.
What I have done below is modified the PostList component, first by forking it and replacing the posts
variable with the filteredPosts
variable. Then, to set the filteredPosts
, the code was written to get all the blog posts and return only those which contained the categories in $categories
array. Admittedly, this method is definitely not the most efficient and could be further improved
Add the following code in the Mark Up
<ul class="post-list">
{% for post in filteredPosts %}
<li>
<h3><a href="{{ post.url }}">{{ post.title }}</a></h3>
<p class="info">
Posted
{% if post.categories.count %} in {% endif %}
{% for category in post.categories %}
<a href="{{ category.url }}">{{ category.name }}</a>{% if not loop.last %}, {% endif %}
{% endfor %}
on {{ post.published_at|date('M d, Y') }}
</p>
<p class="excerpt">{{ post.summary|raw }}</p>
</li>
{% else %}
<li class="no-data">{{ noPostsMessage }}</li>
{% endfor %}
</ul>
{% if posts.lastPage > 1 %}
<ul class="pagination">
{% if posts.currentPage > 1 %}
<li><a href="{{ this.page.baseFileName|page({ (pageParam): (posts.currentPage-1) }) }}">← Prev</a></li>
{% endif %}
{% for page in 1..posts.lastPage %}
<li class="{{ posts.currentPage == page ? 'active' : null }}">
<a href="{{ this.page.baseFileName|page({ (pageParam): page }) }}">{{ page }}</a>
</li>
{% endfor %}
{% if posts.lastPage > posts.currentPage %}
<li><a href="{{ this.page.baseFileName|page({ (pageParam):(posts.currentPage+1) }) }}">Next →</a></li>
{% endif %}
</ul>
{% endif %}
Add the following code in the Code tab of the CMS. To change the
use RainLab\Blog\Models\Post as BlogPost;
function onStart(){
//This is where you list the categories you want to display
$categories = ['cat-a','cat-b'];
$posts = [];
foreach(BlogPost::all() as $blog){
foreach($blog->categories as $cat){
if(in_array($cat->slug, $categories)) {
array_push($posts, $blog);
break;
}
}
}
$this['filteredPosts'] = $posts;
}
Upvotes: 3