I apologise for this post being so long. The REASON for me asking such a stupid question as the topic suggests is BECAUSE there is just so many different things going wrong that I need to provide details of WHY I am asking this question.
Please bear with me...
I am busy creating a custom theme for my personal use have a LOT of slug-based pages and I use WP_query a lot(!) for many things from a custom news ticker to procedurally generating my navbar to mention but a few.
I was under the impression that creating a custom WP_Query means the content inside the results will not interfere with the operation of the main Loop and yet, I get very strange behaviour...
All my custom slug-based pages always work perfectly fine but when I use this in my navagation.php template part:
$query = new WP_Query($args);
if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post();
//do my stuff here
endwhile; endif;
...this results in pages and posts loading just fine during the Loop but when I get to the product I am trying to view it always shows the same product no matter what link I follow. Eventually I added this to the product page:
if (have_posts()) {
the_post();
rewind_posts();
}
...and that made the products load up just fine. Yeay! No idea WHY I have to do it but it works. Strangely enough, though, in the template, just before it loads the template part that does the product layout, I print the name of the post currently in the global $post and then watch as it prints the wrong name above the right product after starting the Loop. (!?)
So then I find out about get_posts() and I like the fact that it gives me an array rather than an object that contains an array and so I swap over to using get_posts() in my navigation.php header template part and now my header section still works perfectly and my products display perfectly... but all posts and pages now show the same content. All posts and pages now show the same WooCommerce product. (!?) What's more confusing is that I do 3 WP_Query calls in navigation.php and the Loop in my posts and pages all show the first entry from the FIRST query, not the last...
After much struggling I decided it wasn't worth the aggravation so I swapped back to using WP_Query. Now things are all messed up in ways I can't even begin to understand... Now my posts and pages work just fine (so does my custom menu) but my products now all show the same product while in the loop. I tried doing this:
global $post;
$current = $post;
//do my query and loop over it
$post = $current;
Somehow that code turns the $post (which is just a pointer into the array) into an array itself (or something) because the product template now first displays the same product on every page I go to and then it displays the $post product it was supposed to directly below it. If I set $post to null directly after I set $current then setting $post back to $current afterwards results in only the wrong page showing up.
Somehow I managed to get it to stop showing the wrong product and now, instead, only my slug-based pages work because anything that uses the Loop (post, page and product) just tells me this:
Fatal error: Uncaught Error: Cannot use object of type WP_Query as array in D:\xampp\wordpress\htdocs\wp-includes\class-wp-query.php:3071 Stack trace: #0 D:\xampp\wordpress\htdocs\wp-includes\class-wp-query.php(3099): WP_Query->next_post() #1 D:\xampp\wordpress\htdocs\wp-includes\query.php(805): WP_Query->the_post()
..and tracking the stack trace to where that occurs seems to indicate that (apparently) I am trying to use a WP_query as an array when I say this during the Loop:
if (have_posts()) : while (have_posts()) : the_post()
How is THAT code wrong? It's straight from the manual! :O According to the Codex, even though get_posts() also uses WP_Query it allows you to have multiple Loops and it says that you should use the restore_post_data() (I think) IF you updated the main Loop contents. But I am NOT trying to modify the main Loop at all. I want to do a query, have the results in a variable, run over that result and then discard the variable before going into the Loop and showing the page content as normal. I want my queries to run independently of the Loop and NOT in any way interfere with the operation of the Loop at all.
So:
- why the heck does my custom WP_Query calls interfere with that I am seeing in the Loop and
- why the heck do I get the error about trying to pass a WP_Query object as an array when calling the default, vanilla Loop
- why do my products display correctly but my posts and pages do not
- or why does my post and pages show correctly while my products show two different products
How the heck can my fully functional site get THIS broken just by going from $posts = get_posts($args) to $query = new WP_Query($args) ???? In a separate job completely outside the Loop, no less!
It makes absolutely no sense and since it makes no sense I have no idea where to start when trying to implement a fix. So what am I not seeing here? rewinding the posts, restoring the post data... nothing helps. I am completely dumbfounded.
Am I not using the Loop correctly? All I want to do is this:
- Load a page that does a custom WP_query and displays the content
- Load the template part that performs the Loop (i.e. single-product)
- Display the template part that page loads (i.e. content-single-product) and have it be the right content
It shouldn't be this hard, should it?
if (have_posts()) : while (have_posts()) : the_post(); /*display the post*/ endwhile; endif;
to this:if (have_posts()) : while (have_posts()) : /*display the post*/ the_post(); endwhile; endif;
And now the page actually shows. Seems my fears were justified about the_post() skipping over the first entry. Okay, so now I see the post displayed but as soon as I call the_post() I am back to receiving the error about the_post using a WP_Query as an array. Sigh :( – user10535901