I am trying to first display four posts with post-format-aside (all assigned to current tag) and then display the "real" archive (exclude post-format-aside) for the specific tag. Right now I am using a function to exclude post format-aside from the main query:

add_action('pre_get_posts', 'keyl_get_emp_posts');
function keyl_get_emp_posts($query) {
if (is_tag()) {
if ($query->is_main_query())
 $taxq = array(
    'tag' => $current_tag,
    array(
        'taxonomy' => 'post_format',
        'field' => 'slug',
        'terms' => array(
            'post-format-aside'
          ),
        'operator' => 'NOT IN'
    )
);

    $query->set('tax_query',$taxq);
}

}

Than I am trying to display the custom query with only post-format-aside with

<div class="row">
<?php $current_tag = single_tag_title("", false);
$args = array(
    'posts_per_page' => 4,
    'tag' => $current_tag,
    'post_type' => array('post', 'renvoeringsdamm'),
    'tax_query' => array(
        array(
            'taxonomy' => 'post_format',
            'field' => 'slug',
            'terms' => array( 'post-format-aside' )
        )
    )
);
$query = new WP_Query( $args );
if ( $query->have_posts() ) {
  while ( $query->have_posts() ) {
    $query->the_post(); ?>
    <div class="col-sm-3 col-xs-6">
        <?php get_template_part( 'content', get_post_format() ); ?>
    </div>
    <?php
  }
      wp_reset_postdata();
} ?>
</div>

But the special query for only post-format-aside is displaying post from all types of post-formats... So my question is really, what is wrong with what I have done so far!..

up vote 1 down vote accepted

I don't suspect that your tax_query is failing you, but actually your tag parameter is. single_tag_title() returns the name of the tag, not the slug.

All tag and category queries are converted to a tax_query in the WP_Query class before being passed to the WP_Tax_Query class to build the relative string for the SQL query. Term names and slugs gets sanitized before validation and before getting the term ID of the passed term/s. (Just for interest sake, read why you should not use term names and the name parameter inside a tax_query, check my answer here)

Now, slugs should always be lowercase and multiple words separated by hyphens. You are passing a name as a slug. Because the term name matches nothing in the term slug column (because you have told the tax_query to look in the slug column), WP_Tax_Query accepts that the term is invalid and does not exist and therefor simply bails out and return an empty string. This is where the big flaw comes in (which in my opinion is a bug that should be fixed). WP_Tax_Query sends an empty SQL join string back to WP_Query, WP_Query wrongly reads this as if there were never a tax_query and continues to build and then executes the SQL without the join clause. This unexpectedly then returns all posts regardless, where in my opinion it should just return no posts at all. This is what you are seeing

So lets look at a solution and also clean up your code and make it more reliable

First, your pre_get_post action

  • Add a check to target the front end only, otherwise back end queries will be affected as well

  • Set is_tag() to the current instance

  • Get the current tax_query on the tag page and modify it to add the the post format section and pass that as a new tax_query

You can adjust your code to something like this: (I'm using closures, but you can revert to the old style as in your question ;-))

add_action('pre_get_posts', function ($q) 
{
    if (    !is_admin() // Only targets front end queries
         && $q->is_main_query() // Only targets the main query
         && $q->is_tag() // Only targets tag archive pages  
    ) {
        // Gets the current tax_query
        $tax_query_obj = $q->tax_query->queries;
        // Add the post format query part to the current tax_query
        $tax_query_obj[] = [
            'taxonomy' => 'post_format',
            'field' => 'slug',
            'terms' => ['post-format-aside'],
            'operator' => 'NOT IN'
        ];
        //Build a proper tax query
        $tax_query = [
            'relation' => 'AND',
            $tax_query_obj
        ];
        // Set the modified tax_query
        $q->set( 'tax_query', $tax_query );

        // Set any additional parameters here except tag parameters
    }
}, PHP_INT_MAX );

As for your custom query, we can get the current tag ID being viewed by simply using get_queried_object_id() and then using that in a tax_query with our post format . You can try the following in your arguments: (Requires PHP 5.4+ due to new short array syntax ([]))

$args = [
    'tax_query' => [
        [
            'taxonomy' => 'post_tag', // Default tag taxonomy
            'terms' => get_queried_object_id(), // Gets current tag archive tag ID
        ],
        [
            'taxonomy' => 'post_format',
            'field' => 'slug',
            'terms' => 'post-format-aside'
        ],
    ],
    // Rest of your arguments excluding tag parameter
];
  • Thanks you for helping me! Although this function seem to "error/whiten" my theme and I can't figure out what part is troubling. I have tried to change the closures to arrays but still can't understand what is wrong.. :( – HannesH Jul 23 '15 at 7:48
  • You should upgrade your php version. I will however rewrite the code for older versions. Please note, all versions older than PHP5.4 is not supported anymore and therefor a huge security risk to your site:-) – Pieter Goosen Jul 23 '15 at 7:54
  • This is really strange, in mamp it says I am running php version 5.5.3 and it doesn't work even when copied your new code. Must this be a php error or could it be something else? Thanks for your time! – HannesH Jul 23 '15 at 8:24
  • Good crap, there is a copy and paste error in my code. Don't know how it creeped in. Sorry about that. Will correct now – Pieter Goosen Jul 23 '15 at 8:58
  • It should work now, sorry for setting you off on a made goose chase :-) – Pieter Goosen Jul 23 '15 at 9:01

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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