5

There are a number of 3rd party wp.org repository plugins that 1) add categories and tags to pages, and 2) enable pages to be displayed along with posts in the archive pages.

The code they use for part 2 always uses:

$wp_query->set

eg:

   if ( ! is_admin() ) {
      add_action( 'pre_get_posts', 'category_and_tag_archives' );
   }

// Add Page as a post_type in the archive.php and tag.php 

function category_and_tag_archives( $wp_query ) {

    $my_post_array = array('post','page');

    if ( $wp_query->get( 'category_name' ) || $wp_query->get( 'cat' ) )
      $wp_query->set( 'post_type', $my_post_array );

    if ( $wp_query->get( 'tag' ) )
      $wp_query->set( 'post_type', $my_post_array );

  }

So the plugins are all modifying wp_query settings and then leaving these settings -- ie they are not unsetting the changes or resetting them.

I guess they cannot reset wp_query because wp_query is not executed immediately after they modify it - wp_query will be executed at a later time when the archive page is called. Since they are not executing wp_query in their code they cannot reset it right after.

Then when I use this code in another plugin, eg:

$the_query = new WP_Query( array( 'cat' => $categoryid, 'post_type' => 'page' ) );

It returns both posts and pages, when it should only return pages.

This is because the wp_query has been modified and not reset.

I do not what to do in this case to get wp_query working for the second chunk of code.

The obvious would be to reset wp_query before my line of code but I am not sure it that will negatively affect other code in other plugins or the core.

Any help is greatly appreciated.

4

If the code shown above is the one the plugin is using, it will affect every query, since it's not checking for is_main_query() (https://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts)

What you could do, is remove the action, do your query, and then add the action again (if needed)

remove_action( 'pre_get_posts', 'category_and_tag_archives' );
$myQuery = new WP_Query($queryArgs);
add_action( 'pre_get_posts', 'category_and_tag_archives' );

If in the plugin it has a different priority (default is 10) make sure to specify it.

Heres the remove action reference https://codex.wordpress.org/Function_Reference/remove_action

Hope this helps,

| improve this answer | |
  • Dear Ignacio, thank you very much for your help! Although I think you have a good solution, the other solution suggested suits me a bit better in this case.... – ironfish Feb 7 '17 at 23:08
  • Alright, just remember that in the other solution you would be modifying plugin code, which would be lost on plugin update. While my solution is removing the running of the plugin filter for the moment in which you execute your custom query. – Ignacio Jose Canó Cabral Feb 8 '17 at 22:00
3

When plugin modify WP_Query it is not modified "for good", but just the single object that is being modified.

When you do:

$the_query = new WP_Query( array( 'cat' => $categoryid, 'post_type' => 'page' ) );

You get both pages and posts, but not because the query is modified and not reset (in fact you are using another object). The real reason is that the filter runs again for this new object, modifying it as well.

This happen because pre_get_posts hook runs for all the queries, so it runs for the original query and for your query as well.

If the plugin that modifies the query had been a bit more wise, it had checked for is_main_query() before modifying the query, this way any query that is not the main query, would not be affected.

For example, if the plugin does:

function category_and_tag_archives( $wp_query ) {

    // Only act on main query
    if ( ! $wp_query->is_main_query() ) {
       return;
    }

    $my_post_array = array('post','page');

    if ( $wp_query->get( 'category_name' ) || $wp_query->get( 'cat' ) )
      $wp_query->set( 'post_type', $my_post_array );

    if ( $wp_query->get( 'tag' ) )
      $wp_query->set( 'post_type', $my_post_array );

}

when after that you do:

$the_query = new WP_Query( array( 'cat' => $categoryid, 'post_type' => 'page' ) );

being this query a secondary query it will not be affected, and you'll get only posts as expected.

| improve this answer | |
  • Dear gmazzap, I appreciate your time and support! – ironfish Feb 7 '17 at 23:05
  • Your solution works like a charm!!! Thanks sooooo much - your solution ended hours of me trying to resolve this..... I ended up writing my own plugin to use this code. I will let existing plugins know that they should consider updating their code... – ironfish Feb 7 '17 at 23:06

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.