There have been countless times where I’ve run into strange issues with my WordPress templates not working as I expect they should after using one of WordPress’s method for creating a new query and starting an independent loop.
It’s a class called WP_query. Here’s a short blurb about this class from the function reference page.
WP_Query is a class defined in
wp-includes/query.phpthat deals with the intricacies of a request to a WordPress blog. The wp-blog-header.php (or the WP class in Version 2.0) gives the $wp_query object information defining the current request, and then $wp_query determines what type of query it’s dealing with (category archive? dated archive? feed? search?), and fetches the requested posts.
Whilst that above quote will likely make most people’s minds instantly turn off, it’s actually quite simple to use and can be instantiated by, for example, assigning it to a variable:
$myQuery = new WP_query();
From there you can easily switch to running your normal WordPress query and loop (with a few minor modifications).
I moved to using this method quite a while ago as I believed it was a way to ensure that you didn’t play havoc with other queries occurring in your template on that particular page.
Moving on from the above instantiation, it’s possible to run multiple WordPress queries (within the WP framework) and set up as many loops as you like. An example might be a very custom sidebar setup:
$specialWidget = new WP_query(); $specialWidget->query($args1); if ($specialWidget->have_posts()) : while ($specialWidget->have_posts()) : $specialWidget->the_post(); // do loop stuff endwhile; else : // do stuff for no results endif; $superWidget= new WP_query(); $superWidget->query($args2); if ($superWidget->have_posts()) : while ($superWidget->have_posts()) : $superWidget->the_post(); // do loop stuff endwhile; else : // do stuff for no results endif; $megaMidget= new WP_query(); $megaMidget->query($args3); if ($megaMidget->have_posts()) : while ($megaMidget->have_posts()) : $megaMidget->the_post(); // do loop stuff endwhile; else : // do stuff for no results endif;
The issue that I encountered was in the case of a client site. I had a custom page template, which rather than showing that page’s the_content(), it was running a query to get a selection of posts from a specific category. For URL consistency and other factors I didn’t want to just direct users to the category page.
I noticed problems when the sidebar (loaded via footer.php) was no longer correctly showing the child pages of the overall section. The function in the footer was dependent on
and this was no longer getting the actual ID of the current page. I discovered after a quick investigation, that it was now assuming the ID of the current page to be that of the last post queried by my new WP_query class.
I had assumed that use of the WP_query class negated issues such as these, but I was wrong.
I had searched for solutions to this issue before but had always come up with suggestions like assigning your query to a temp var, and then resetting that, such as:
$temp = $wp_query; $wp_query = new WP_Query(); $wp_query->query($args); //do stuff $wp_query = $temp;
But such solutions never worked for me, and I think I always ended up going off and doing stranger methods of achieving my queries, using things like get_posts and other options.
It’s so mind bogglingly simple I’m amazed I’ve never come across it before. Once you’re done with your custom WP_query loop, just add this line, and you’ll never have to worry about your custom WordPress query breaking other areas of your template.
That’s all there is to it. I came across it in the WordPress Support Forums, a wonderful place for solutions as always.
I’m off to update the Codex page for WP_query with this important little nugget of information.
Photo from flickr user: theadz01