I've got post type called "Portfolio" and single-portfolio.php file to handle it (it's WordPress). When I use there something like that it works like expected:
$post_id = $post->ID; //returns ID of current portfolio post. Good!
BUT when I post short query like this in the middle:
$post_id = $post->ID; //returns ID of current portfolio post. Good!
wp_reset_query();
query_posts('posts_per_page=4');
if ( have_posts() ) : while ( have_posts() ) : the_post();
the_id(); //returns ID of standard blog post
endwhile;
endif;
wp_reset_query();
$post_id = $post->ID; //returns ID of last BLOG post. Wrong!
I'm only concerned about $post_id variable in above example. I want it to always return correct ID of current PORTFOLIO post and not be dependent on other queries. How do I achieve that?
I believe wp_reset_postdata() will give you the result you are looking for.
$the_query = new WP_Query( 'posts_per_page=4' );
if ( $the_query->have_posts() ) :
while ( $the_query->have_posts() ) : $the_query->the_post();
// output
endwhile;
endif;
wp_reset_postdata();
I should note that there is another approach which I have documented in another question asking about what is the difference and when each should be used.
The wp_reset_query function does reset the global $post variable as well, but only based on the global $wp_query variable. That still is modified, probably due to one of the little flaws in Wordpress. In your case I'd say a simple WP_Query::rewind_posts() should do it:
wp_reset_query();
$wp_query->rewind_posts();
$post_id = $post->ID;
Also you should consider to create a second loop, not overwrite the first one.
See as well:
Wordpress wp_reset_query() does not go back to last query?
Related
I have spent some time reading through the WordPress Codex, as well as various themes, and can see that some developers insert <?php wp_reset_postdata(); ?> after the endif; in a Blog Loop whilst others insert the code between the endwhile; and endif; of a Blog Loop. I have tried both locations but have yet to see a difference. Is there a correct location?
This function supposed to reset the secondery query that you run.. the function the_postis letting you to use all the functions that you can run in the loop like the_title() the_content and so on..
So you reset the the_post function and after the endwhile; you can reset it already. and use your main query inside the if statment too if you like.
<?php
// this is the main query check if there is posts
if ( have_posts() ) :
// loop the main query post and run the_post() function on each post that you can use the function the_title() and so on..
while ( have_posts() ) : the_post();
the_title(); // title of the main query
// the is second query
$args = array( 'posts_per_page' => 3 );
$the_query = new WP_Query( $args );
// check if there is a posts in the second query
if ( $the_query->have_posts() ) :
// run the_post on the second query now you can use the functions..
while ( $the_query->have_posts() ) : $the_query->the_post();
the_title();
the_excerpt();
endwhile;
// reset the second query
wp_reset_postdata();
/* here we can use the main query function already if we want..
its in case that you want to do something only if the second query have posts.
You can run here third query too and so on...
*/
the_title(); // title of the main query for example
endif;
endwhile;
endif;
?>
wp_reset_postdata() is only required if you have a secondary loop (you're running additional queries on a page). The purpose of the function is to restore the global post variable back to the current post in the main query.
Example:
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
OUTPUT MAIN POSTS HERE
<?php endwhile; endif; ?>
In the code above I'm simply using the main loop to display posts. There's no reason to include wp_reset_postdata(). The global post variable is exactly what it's supposed to be.
If somewhere else on the page I decide to add a secondary loop, then I'll need wp_reset_postdata().
// This query is just an example. It works but isn't particularly useful.
$secondary_query = new WP_Query( array(
'post_type' => 'page'
) );
if ( $secondary_query->have_posts() ) :
// Separating if and while to make answer clearer.
while ( $secondary_query->have_posts() ) : $secondary_query->the_post();
// OUTPUT MORE STUFF HERE.
endwhile;
wp_reset_postdata();
endif;
To answer your original question: it usually comes after endwhile and before endif. It's the call to the_post() which actually changes the global post variable. If there are no posts then the post variable remain the same and there's no reason to use the reset function.
I am creating a wp template based on 2013. I want to display a 'page' that has some content from a page and then 6 posts on it. These posts have been selected via the themes options panel using the settings api. So I can get at each one using
$options = get_option( 'osc_theme_options' );
The template i have been using so far is based on a page so i am guessing I need to change the loop in someway.
The loop goes:
<?php /* The loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>...
I want to know how to alter the loop so that it pulls in just the posts that have been selected. At the moment this template/loop is only pulling in the page - which I guess is fair enough.
Would it be possible to create 'another loop' maybe under the first that then brings in the selected posts - if so how?
Many thanks
Yes you can effectively create another loop under the existing loop to display the posts. I am not sure what $options = get_option( 'osc_theme_options' ); returns, i.e an array of Post ID's etc. In order to show the posts you need to do a custom loop:
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() )
{
echo '<ul>';
while ( $the_query->have_posts() )
{
$the_query->the_post();
echo '<li>' . get_the_title() . '</li>';
}
echo '</ul>';
}
else
{
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
This is taken from:
https://css-tricks.com/snippets/wordpress/custom-loop-based-on-custom-fields/
Also see the following:
https://digwp.com/2011/05/loops/
http://www.smashingmagazine.com/2013/01/14/using-wp_query-wordpress/
So effectively it all boils down to the $args variable as to which posts you will get. Here is an example of multiple ids
id=2,6,17,38
So if $options = get_option( 'osc_theme_options' ); returns an array of post ids like so:
array(
0=>1
1=>22
2=>27
)
You could probably do something like:
$args = "id=".implode($options,",");
This is the best advice I can give without deeper knowledge of the theme etc.
I've a weird problem, some posts appears in categories where they are not in.
When I look in my backoffice and filter by categories, some post appears there but they are not checked in.
The resultat is that in the front office they appear too.
This is my category.php (but I don't think it's the matter)
<?php
get_header();
?>
<section id="wrapper" class="page <?php echo get_query_var('cat'); ?>">
<div id="container">
<?php
$category = get_category(get_query_var('cat'));
$cat_id = $category->cat_ID;
query_posts('showposts=1&cat='.$cat_id);
if ( have_posts() ) :
while ( have_posts() ) : the_post();
get_template_part( 'content', get_post_format() );
endwhile;
endif;
?>
</div>
</section>
<?php
get_footer();
?>
I looked in the table "_term_relationships" and everything is right, they're not in the wrong categories.
So maybe someone have a clue to find out ?
PS : I'm using WPML, but if I desactive it, it's the same problem
You should not use query_posts(),
see (https://wordpress.stackexchange.com/questions/1753/when-should-you-use-wp-query-vs-query-posts-vs-get-posts)
try this:
<?php
$category = get_category(get_query_var('cat'));
$cat_id = $category->cat_ID;
$args = array( 'category' => $cat_id );
$query2 = new WP_Query($args);
if ( $query2->have_posts() ) :
while ( $query2->have_posts() ) :
$query2->the_post();
get_template_part( 'content', get_post_format() );
endwhile;
endif;
?>
First of all, never use query_posts to construct any type of query
Note: This function isn't meant to be used by plugins or themes. As explained later, there are better, more performant options to alter the main query. query_posts() is overly simplistic and problematic way to modify main query of a page by replacing it with new instance of the query. It is inefficient (re-runs SQL queries) and will outright fail in some circumstances (especially often when dealing with posts pagination).
Secondly, never change the the main query for a custom query on any type of archive page or home page. The correct way is to use pre_get_posts to alter the query variables before the main query executes. Check out this post I've done a while ago
Thirdly, category pages in Wordpress does work in a strange way. When a category page is visited, it will display posts from the selected category and posts from the selected category's child categories. I bet this is what you are seeing. This is pretty normal behavior. If you need to change this, have a look at this answer on WPSE by #ialocin. For the benefit of this answer, here is the solution
add_filter(
'parse_tax_query',
'wpse163572_do_not_include_children_in_category_archive_parse_tax_query'
);
function wpse163572_do_not_include_children_in_category_archive_parse_tax_query( $query ) {
if (
! is_admin()
&& $query->is_main_query()
&& $query->is_category()
) {
// as seen here: https://wordpress.stackexchange.com/a/140952/22534
$query->tax_query->queries[0]['include_children'] = 0;
}
}
I have following array:
array (12,15,21,32,33);
And then I use the following query to get the posts (of the above of IDs):
$the_query = new WP_Query( array("post__in"=>$ids_array) ); // edited
while($the_query->have_posts())
{
$the_query->the_post(); // added on edit, but still does not work
the_title()."<br />";
}
But I get nothing, no error and no interruption. I have checked the IDs and they are correct.
EDIT: I have put this query at the end of a module which is loaded into the footer. I don't know if it is important or not:
You forgot to add while ( $the_query->have_posts() ) : $the_query->the_post();.
You are just checking to see if you have posts, but doing nothing further
$ids_array = array (12,15,21,32,33);
$the_query = new WP_Query( array('post__in'=>$ids_array) );
<?php if ( $the_query->have_posts() ) : ?>
<?php while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<h2><?php the_title(); ?></h2></br>
<?php
endwhile;
wp_reset_postdata();
endif;
?>
EDIT
I think the underlying problem here is not this custom query, as this custom query works. It seems from your comments that you are using another custom query on the same page.
I don't know what the code of the first query looks like, but here are some troubleshooting points you need to go and have a look at
Most probably you did not reset the postdata on your first query. This will break your second query. wp_reset_postdata is extremely important when you are running custom queries with WP_Query and with get_posts. Check that you have used wp_reset_postdata after your first instance of WP_Query. Your first query should be in the same format as the one in my answer
You should use different variables for each instance of WP_Query. For example $variable1 = new WP_Query( YOUR ARGUMENTS ) for first instance and $variable2 = new WP_Query( YOUR ARGUMENTS ) for your second instance
I've decided to start using wp_query instead of query_posts, on my home page I want to call the content from a particular page inside a div. Just wondering what am I missing here as nothing is appearing and I do have a page with content with an ID of 140. Im still quite new to this thanks!
<div class="home-info" >
<?php
if (have_posts() ) :
$the_query = new WP_Query( 'paged=140' );
while ($the_query->have_posts() ) : $the_query->the_post();
echo the_content();
endwhile;
wp_reset_postdata();
endif;
?>
</div>
You've used the wrong argument in WP_Query, it should be page_id rather than paged. Here's the reference from the Codex;
http://codex.wordpress.org/Class_Reference/WP_Query#Post_.26_Page_Parameters