Midhun Babu
Midhun Babu

Reputation: 129

How to filter blog posts with multiple categories in octobercms?

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

Answers (2)

Gregorio
Gregorio

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

Nick
Nick

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

  1. Add the PostList component to the page
  2. 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) }) }}">&larr; 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 &rarr;</a></li>
            {% endif %}
        </ul>
    {% endif %}
    
  3. 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

Related Questions