6

I need the user to be able to sort and filter the posts when viewing a category. The correct way to make a category page would be to use category(-{id}/{slug}).php, but using that automatically creates a loop, so no matter what method I use to sort and filter the posts it will make another loop.

In that case should I make a file that's not called category(-{id}/{slug}).php and somehow link it to the categories, or would it be better to simply ignore that two loops are being made no matter what and one of them will not be used?

Also in that case is using the Loop again, but with the modified query, more efficient than get_posts()?

2 Answers 2

5

Yes, the loop and a specific category template should be used even if you want to customize the query. Why?:

  1. Even with a custom page, the main query will run. So with a custom page, you are not actually avoiding the main query, you are only replacing it with a different query.

  2. The main query itself is customizable.

  3. If you deviate from the default WordPress behaviour, it'll be difficult for you to maintain in the future, especially it'll be difficult for other developers in case someone else takes over your work in the future.

How to modify the main query:

Fortunately, WordPress is extremely customizable, that means the main query (the loop) is also customizable. You may use the pre_get_posts action hook or query_posts() function to alter the main query. However, it's recommended to use the pre_get_posts hook.

For example, say you want to change the order of posts in a category based on ascending order of date. For that you may use the following CODE in your theme's functions.php file:

add_action( 'pre_get_posts', 'wpse258109_customize_category_query' );
function wpse258109_customize_category_query( $query ) {
    if( ! is_admin() && $query->is_main_query()  && $query->is_category( 'your-category-slug' ) ) {
        // get the orderby value from where ever you want and set in the main query
        $query->set( 'orderby', array( 'date' => 'ASC' ) );
    }
}

This CODE will change the default behaviour of the main query and your category posts for your-category-slug archive page will load in ascending order. Of course you can make any change to this main query as you can with any custom query using the WP_Query class.

2
  • Is it possible for the query I want to be so complex that it can't be executed with WP_Query alone? I might need to write it in SQL. In that case would I be left with no choice but to leave the main query unused?
    – Nadroev
    Commented Feb 27, 2017 at 15:43
  • Well you can do a lot of complex queries with WP_Query, check out get_posts() function to see what hooks are available: core.trac.wordpress.org/browser/tags/4.7.2/src/wp-includes/…. However, for the sake of argument, let's say your query can't be handled by all those hooks, then it should be possible to extend WP_Query with your custom class that can handle the query. I haven't tried that because I never needed it. But I don't see why it can't be done.
    – Fayaz
    Commented Feb 27, 2017 at 16:06
2

First of all: Great you're thinking about a wasted query! :)

Second: WP always runs a main query no matter what you do. But what you can do is alter this query instead of ignoring it and creating a secondary loop. This can be done using the pre get posts hook.

2
  • If there is always a main query no matter what, then what is the point of ever using anything other than pre_get_posts?
    – Nadroev
    Commented Feb 27, 2017 at 14:53
  • 1
    Having multiple queries/loops? Not knowing about the hook? :)
    – kraftner
    Commented Feb 27, 2017 at 15:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.