Each of these bits of code work separately in category.php, but when I use both together, the first one is ignored. Can someone tell me how to combine them into a single piece of code, or at least make them play nicely together?

<?php if (is_category())
{ $posts = query_posts( $query_string . '&orderby=title&order=asc&posts_per_page=18' );
} ?>

<?php $current_cat = intval( get_query_var('cat') );
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
'category__and' => array($current_cat),
'paged' => $paged,
'post_type' => 'post',
'caller_get_posts'=> 1

As already stated, you should never use query_posts as it breaks the main query and many functionalities that other code and plugins rely on

Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).

Also, you should never replace the main query with a custom one. This raises more issues that solving the one you have tried to solve in the first place. Read this post on this issue

This all being said, you are going to make use of pre_get_posts to alter the main query to change the order of posts to be sorted by title. Then you are going to use parse_tax_query to remove the child categories from the category pages

You can do something like in your functions.php

add_action( 'pre_get_posts', function ( $q )
    if (   ! is_admin() 
        && $q->is_main_query()
        && $q->is_category()
    ) {
         * Set the order so that posts are ordered by post title
        $q->set( 'orderby', 'title' );
        $q->set( 'order', 'ASC' );
         * Ignore sticky posts, this is the correct syntax to use
        $q->set( 'ignore_sticky_posts', true );

         * Filter the tax query to remove child categories from category pages
        add_filter( 'parse_tax_query', function ( $q ) 
            if ( $q->is_main_query()
            ) {
                $q->tax_query->queries[0]['include_children'] = 0;

Also, as already pointed out, caller_get_posts is depreciated and is replaced by ignore_sticky_posts.

Lastly, your category.php should look something like this

if ( have_posts() ) {
    while ( have_posts() ) {

        // Your HTML Mark up and template tags etc


Don't use query_posts() ;).

In short query_posts() over-rides the global $wp_query. So subsequent calls replace previous ones. Instead you should use pre_get_posts:

function wpse183914_filter_child_cats_and_order( $query ) {

    //Alter front-end main query for categories only.
    if ( $query->is_main_query() && $query->is_category() && !is_admin() ) {
        $cat_id = $query->get_queried_object_id();
        $child_cats = (array) get_term_children( $cat_id, 'category' );

        //exclude the posts in child categories
        $query->set( 'category__not_in', $child_cats );

        //Set sort order
        $query->set( 'orderby', 'title' );
        $query->set( 'order', 'asc' );

        //Exclude sticky (see remark at bottom)
        $query->set( 'ignore_sticky_posts', true );
add_filter( 'pre_get_posts', 'wpse183914_filter_child_cats_and_order' );

(As an aside caller_get_posts is deprecated).

  • Thank you for responding, but that doesn't work at all. It's not alphabetized and child posts are displaying. I took out && !is_admin() and no change. – lkl Apr 12 '15 at 1:33
  • Can you confirm that it passes the conditional? If no, which one is failing? – Stephen Harris Apr 13 '15 at 20:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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