0

I am displaying results from a custom post type ("works") and want to optionally filter by a custom taxonomy ("genre") if that is set (i.e. if the loop is on the custom taxonomy archive template).

I am using a wp_query with arguments, but it is not filtering by the custom taxonomy slug- it's returning all results.

For your information, I am ordering by a custom post type and I am paginating results (not included the code for that in this example). I set the custom post type, custom fields and custom taxonomy using the Types plugin, but I am not sure if that makes a difference to this question.

Here is the code:

if($wp_query->query->genre != "") {
    $genre = $wp_query->query->genre;
}

if($genre != "") {
    $taxArray =     array(
        'taxonomy' => 'genre',
        'field'    => 'slug',
        'terms'    => $genre,
    );
    $args = array(  
        'post_type' => 'works', 
        'posts_per_page' => 40, 
        'meta_key' => 'wpcf-composition-date', 
        'orderby' => 'wpcf-composition-date', 
        'order'   => "DESC",
        'offset'     =>  $offset,
        'tax_query' => $taxArray
    );
    $loop = new wp_query( $args );
    while ( $loop->have_posts() ) : $loop->the_post();
    ?>
        <?php get_template_part('templates/content-works', get_post_format()); ?>
    <?php endwhile; ?>

Just to clarify, here is the output of $args from the page that uses the above code:

Array
(
    [post_type] => works
    [posts_per_page] => 40
    [meta_key] => wpcf-composition-date
    [orderby] => wpcf-composition-date
    [order] => DESC
    [offset] => 0
    [tax_query] => Array
        (
            [taxonomy] => genre
            [field] => slug
            [terms] => Array
                (
                    orchestral
                )

        )

)

As I said, the above code lists all results from all custom taxonomies.

Is there an error in my code? What am I doing wrong? How can I display results filtered by the custom taxonomy slug?

Update... Just looked at the request and it seems the tax_query isn't being added to the query:

SELECT SQL_CALC_FOUND_ROWS  testweb_posts.ID FROM testweb_posts  INNER JOIN testweb_postmeta ON ( testweb_posts.ID = testweb_postmeta.post_id ) WHERE 1=1  AND testweb_posts.post_type = 'works' AND (testweb_posts.post_status = 'publish' OR testweb_posts.post_status = 'private') AND ( 
  testweb_postmeta.meta_key = 'wpcf-composition-date'
) GROUP BY testweb_posts.ID ORDER BY testweb_posts.post_title ASC LIMIT 0, 40
  • 1
    Use pre_get_posts to amend the main query. Do not use custom queries in place of the main query on any type of archive page. They are troublesome :-) – Pieter Goosen Feb 16 '15 at 11:26
  • Unfortunately that's not going to be possible with my current set up (for various reasons). Why are custom queries on archive pages specifically troublesome? I don't see why they shouldn't work. – baritoneuk Feb 16 '15 at 12:38
  • Why will it not be possible. Just for starters, on each page load you are running the same query twice, it is slow, double the amount of db calls and pagination has to be tweaked to work almost 100 percent, this just to get the same posts :-) – Pieter Goosen Feb 16 '15 at 12:42
  • Good point about the double db calls. I'll have to have another look at the code. It would mean a substantial rewrite of a lot of code- something I was hoping to avoid in the short time frame I have. – baritoneuk Feb 16 '15 at 14:38
  • No, this should be very easy and fast. Remove your custom query and go back to the default loop. Move all your conditions into pre_get_posts in your functions.php – Pieter Goosen Feb 16 '15 at 15:08
1

As I stated in comments, use pre_get_posts to alter the main query. Never replace the main query with a custom one. Again, from comments

Just for starters, on each page load you are running the same query twice, it is slow, double the amount of db calls and pagination has to be tweaked to work almost 100 percent, this just to get the same posts :-)

You can also check out this post I have done on the subject

To make the transition is quite easy, easier than you think. Here is how

  • Create a taxonomy.php template

  • Add the following in there (I have added php tags to make space for your HTML mark up)

    <?php
        while ( have_posts() ) { 
            the_post();
    ?>
            <?php get_template_part('templates/content-works', get_post_format()); ?>
    <?php
        }
    ?>
    
  • Now, you have to move your conditions to functions.php inside pre_get_posts (Requires PHP 5.3+)

    add_action('pre_get_posts', function ($q) 
    {
        if(!is_admin() && $q->is_main_query() && $q->is_tax()) {
    
            $q->set('post_type', 'works'); 
            $q->set('posts_per_page', 40);  
            $q->set('meta_key', 'wpcf-composition-date');  
            $q->set('orderby', 'wpcf-composition-date'); 
            $q->set('order', 'DESC'); 
    
        }
    
        return $q;
    }
    

This should be enough to make things work

  • Thanks, Pieter. I think I understand. I'll spend a bit of time later rewriting the code and see if I can get this to work. Since I need to pass a few strings to change the order and orderby I assume I can pass that via the function? The other question, is how do I change the post type depending on the template page the pre_get_posts function is called? Currently in your example, only the "works" post type will be called. I have a few other post types with their own templates. – baritoneuk Feb 17 '15 at 9:22
  • On the order and orderby parts, yes, you can pass this inside the pre_get_posts action. For the last part of your comment, I don't understand you too well. Normally, by default, the post_type parameter is set to any on taxonomy pages. So if you click on a term, it will display posts from all post types that has the specific term coupled to it. You can just simply remove the post type parameter from my code. – Pieter Goosen Feb 17 '15 at 9:36
  • Sorry for the delay, I hadn't managed to get round to testing this until today. It works really well - thanks! How do I pass the $orderby and $order variables to the pre_get_posts action? They are set in the taxonomy template, but not sure how I can pass them on to the action. And secondly, the template's pagination (older/newer posts) doesn't work anymore. Do you know why this would be the case? – baritoneuk Feb 23 '15 at 18:15
  • I don't understand how your orderby parameters is set in your taxonomy page. You will need to file an edit and explain how you are doing this. If you are setting that through some custom option setting, you are saving it somewhere, correct? Just pass that option to the proper key values in my code. Your pagination will break as you are using pagination for custom loops. Just go back to proper normal pagination. – Pieter Goosen Feb 23 '15 at 18:23
  • Well they orderby parameters were set by GET paramaters. I've figured that one out, thanks. Sorry, but I don't understand what to do about the pagination. I'm using the pre_get_posts action and a normal loop. Should the normal older/newer posts links come up (assuming I use the standard code)? It isn't currently. – baritoneuk Feb 23 '15 at 22:02
0
$args = array(  
    'post_type' => 'works', 
    'posts_per_page' => 40, 
    'meta_key' => 'wpcf-composition-date', 
    'orderby' => 'wpcf-composition-date', 
    'order'   => "DESC",
    'offset'     =>  $offset,
    'tax_query' => array(
        'taxonomy' => 'genre',
        'field'    => 'slug',
        'terms'    => array('orchestral'),
    );
);

Could you please try this code for the sake of testing purposes ? Let me know what this query returns.

  • Thanks. Looking at the above, it looks like the only difference is the 'terms' being set as an array. I had tried that before to see if it was any different and unfortunately not: SELECT SQL_CALC_FOUND_ROWS testweb_posts.ID FROM testweb_posts INNER JOIN testweb_postmeta ON ( testweb_posts.ID = testweb_postmeta.post_id ) WHERE 1=1 AND testweb_posts.post_type = 'works' AND (testweb_posts.post_status = 'publish' OR testweb_posts.post_status = 'private') AND ( testweb_postmeta.meta_key = 'wpcf-composition-date' ) GROUP BY testweb_posts.ID ORDER BY testweb_postmeta.meta_value DESC LIMIT 0, 40 – baritoneuk Feb 16 '15 at 12:39
  • Could you please format your comment by using the Code mark-up ? I can barely read it :) – cristian.raiber Feb 16 '15 at 12:49
  • SELECT SQL_CALC_FOUND_ROWS testweb_posts.ID FROM testweb_posts INNER JOIN testweb_postmeta ON ( testweb_posts.ID = testweb_postmeta.post_id ) WHERE 1=1 AND testweb_posts.post_type = 'works' AND (testweb_posts.post_status = 'publish' OR testweb_posts.post_status = 'private') AND ( testweb_postmeta.meta_key = 'wpcf-composition-date' ) GROUP BY testweb_posts.ID ORDER BY testweb_postmeta.meta_value DESC LIMIT 0, 40 – baritoneuk Feb 16 '15 at 14:36
  • It won't work, a tax_query should be an array of an array, not just an array – Pieter Goosen Feb 23 '15 at 18:30

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.