Preserving postdata with embedded wp_query queries? - php

I'm designing a website in Wordpress. This site is one of those parallax sites where all the pages are printed on the homepage and the menu scrolls to the anchors.
That being said I am using a wp_query to pull out all the pages that are in the main menu. Furthermore I have a shortcode that I use in the content that also requires the use of wp_query.
The problem I have is that the shortcode (the embedded wp_query) is screwing up the postdata. I know when using wp_query you'd usually want to use wp_reset_postdata but in this particular situation it doesn't work because this function call will restore the postdata of the homepage and not of the currently running wp_query (sorry if I'm being unclear).
Is there a way to take a snapshot of the postdata to then restore after my shortcode? I'm looking for something along the lines of:
function my_shortcode() {
save_postdata(); //saves the current postdata
$query = new WP_Query();
while( $query->have_posts() ) {
$query->the_post();
echo get_the_title();
}
my_wp_reset_postdata(); //restores the postdata to where it was before the loop
}

By looking in the source for wp_reset_query(), you will see that what it does is that it simply restores the $wp_query global variable from another global variable($wp_the_query - this is set-up together with the initial set-up for $wp_query, so it holds the original query).
What you can do is you can simply assign $wp_query to a different global variable and then later restore it. Here's an example:
function _save_query( $var = '_wp_query' ) {
$GLOBALS[ $var ] = $GLOBALS['wp_query'];
}
function _wp_reset_query( $var = '_wp_query' ) {
$GLOBALS['wp_query'] = $GLOBALS[ $var ];
wp_reset_postdata();
}
So simply call _save_query() before overwriting the query(you can pass a custom variable name - this way you can store multiple WP_Query objects :) ).
Once you want to restore the query data, call _wp_reset_query() - again you can pass a string as a variable name in order to restore this exact query object.

This is how I managed to get it working, credit goes to Nikola's question since I worked off of his idea.
function _save_query( $var = '_wp_query' ) {
global $post;
$GLOBALS[ $var ] = $post;
}
function _wp_reset_query( $var = '_wp_query' ) {
global $post;
$post = $GLOBALS[ $var ];
setup_postdata( $post );
}
I looked at the documentation of how the loop works found here. I decided to use the same kind of setup as in Nikola's answer since it met my criteria but I used the implementation of the_post to restore the postdata. This is probably not very efficient since it's using the setup_postdata function (which I assume is overkill) but it has definitely solved my problem.
So now when I embed a wp_query I can just do the following:
_save_query();
$products = new WP_Query( $args );
if( $products->have_posts() ) {
$ob .= '<ul class="group-posts">';
while ( $products->have_posts() ) {
$products->the_post();
$ob .= '<li>'.get_the_title().'</li>';
}
_wp_reset_query();
$ob .= '</ul>';
}
Side question/note: What's the etiquette for marking an answer as the correct answer? I'd feel bad accepting my answer as the correct one when Nikola helped me reach it?

my_wp_reset_postdatadoes not exist. You have to use wp_reset_postdata(). But in a situation where you have to chain multiple wp_queries and come back to the older ones, you can store your first query in a variable, set the new WP_query, then reset it and come back to the old one.
$wp_query stores the current loop. So you can go something like :
$temp = $wp_query;
$wp_query= null;
$wp_query = new WP_Query($args);
...
// then later
$wp_query = $temp;
// And back on tracks !

Related

Unable to query using WP_Query with new database instance

I'm writing REST api in wordpress. The api is in OOP format. I created new instance of $wpdb and the connection works just fine. the only problem I'm unable to query database via WP_Query(). But using normal sql, I can get the result.
Whenever I query using WP_Query, it's seems like returning me, the table columns with null value.
FAILS
$args = array(
'post_type' => 'custom_type'
);
$result = new WP_Query($args);
SUCCESS
$query = "SELECT * FROM table_name WHERE post_type ='custom_type'";
$result = get_results($query);
I also tried adding slash before WP_Query like this to no avail:
$result = new \WP_Query($args);
Where's my mistake here? Someone please advise me. Thanks in advance.
You should call have_posts() function in wpquery object
$query2 = new WP_Query( $args2 );
if ( $query2->have_posts() ) {
// The 2nd Loop
while ( $query2->have_posts() ) {
$query2->the_post();
echo '<li>' . get_the_title( $query2->post->ID ) . '</li>';
}
// Restore original Post Data
wp_reset_postdata();
}
I kindly suggest you to use query_posts instead of WP_Query and reset postdata after query.
query_posts lets you to use pagination, excerption and other features.
After query_posts you're free to use a simple wploop

Hide post from displaying in wordpress

I've inherited a wordpress site and I am having a hard time understanding how posts are being displayed. I want to hide a couple from view (but still be able to give out a URL to view them). I'm not familiar with the way a particular template was coded. The template outputs an image and blurb for each event in a certain category. The meat of code that is spitting this out look like this:
<?php
$args['post_type']='seasonalevents';
$args['posts_per_page']=-1;
$args['orderby'] = 'menu_order';
$activities = new WP_Query( $args );
while ( $activities->have_posts() ) : $activities->the_post();
$image_id = get_post_thumbnail_id();
$image_url = wp_get_attachment_image_src($image_id,'thumb_345_154', true);
?>
Is there any way I can exclude post ID's within the code above? Any hints or tips? Feel totally baffled by this. The variables are defined above this code snippet. I can post if needed.
thanks!
The wordpress-y way to do this would be to add an element to the $args array under the three you already have:
$args['post__not_in'] = array(123,456,789);
Where 123, 456, and 789 are the ids of the posts you want to exlude from showing on this page.
So your whole code would look like:
<?php
$args['post_type']='seasonalevents';
$args['posts_per_page']=-1;
$args['orderby'] = 'menu_order';
$args['post__not_in'] = array(123,456,789);
$activities = new WP_Query( $args );
while ( $activities->have_posts() ) : $activities->the_post();
$image_id = get_post_thumbnail_id();
$image_url = wp_get_attachment_image_src($image_id,'thumb_345_154', true);
?>
Yes there is!
You can get the current post's ID using http://codex.wordpress.org/Function_Reference/get_the_ID
I recommend you looking into 'the loop' and what that is.
This code snippet should do the job :-)
...
$not_these = array(1, 2, 7 /* array with post id's you got somewhere */);
while ( $activities->have_posts() ) : $activities->the_post();
if(in_array(get_the_ID(), $not_these)) continue;
...
The easiest solution is to unpublish that post from your administration panel.
Or
<?php
// The Loop
while($query->have_posts()):
$query->the_post();
if(get_the_ID()!=YOUR_POST_ID):
?>
<!-- Show Post -->
<?php
endif;
endwhile;
?>

Wordpress WP_Query for multiple IDs returns null

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

Calling a specific row in single.php wordpress

I am trying to call a single row in each wordpress post. I was thinking that the best way to go around this is to insert a piece of code in the single.php file where I call via the post id:
<?php
$result = "SELECT post_date FROM wp_posts WHERE ID = get_the_ID()";
$row = mysql_fetch_assoc($result);
echo $row['post_date'];
?>
However this doesn't seem to work. Can anyone shed some light on why this isn't working?
Thanks!
WordPress offers a nice database abstraction layer to remove your need to read the posts table directly. It's apparent from your use of get_the_ID() that you're working with the "current" post or page in your code. So, guess what? That row of the posts table has already been loaded by WordPress. Try something like this to retrieve it.
$post = get_post();
echo $post->post_date;
See http://codex.wordpress.org/Function_Reference/get_post for more information.
The get_the_ID() in wordpress is a PHP function, not a SQL function. So try:
$result = "SELECT post_date FROM wp_posts WHERE ID = ".intval(get_the_ID());
*intval force the use of a number, and avoid the SQL injection.
<?php
global $post;
// $ids is an array with the required id's
$ids = array(1,2,24,234,2342);
$args = array(
'include' => $ids,
);
$myposts = get_posts($args);
//You always need $post, because setup_postdata assings eveyrhing to post...
//thats a Wordpres...way of things...
foreach($myposts as $post): setup_postdata($post):
the_time('F jS, Y');
//Don't forget to reset postdata
wp_reset_postdata();
endofreach;

wordpress pagination not working?

My code is
I have written this code for pagination before my loop
$arrangement = get_cat_ID('arrangement');
$antiquarianism = get_cat_ID('antiquarianism');
$paged = (get_query_var('page')) ? get_query_var('page') : 1;
print_r($paged);
$query = query_posts(array(
'page' => intval($paged),
'category__not_in' => array($arrangement, $antiquarianism ) ));
every time its printing 1.
Have you tried a var_dump of $paged? Or resetting the get_query_var('page') as suggested here : worpress support
I have had a similar issue before. Unfortunately it could be a number of things.
One possibility is the treatment of the page query in relation to the Wordpress 'loop'. I was just reading through the documentation for query_posts and spotted this:
Preserving the Original Query (Pagination etc.)
By default running query_posts will completely overwrite all existing query variables on the current page. Pagination, categories dates etc. will be lost and only the variables you pass into query_posts will be used.
If you want to preserve the original query you can merge the original query array into your parameter array:
global $wp_query;
query_posts(
array_merge(
array( 'cat' => 1 ),
$wp_query->query
)
);
http://codex.wordpress.org/Function_Reference/query_posts
I'm not sure if this affects you, but it's worth shot.
EDIT: you could also try running a seperate get_post loop after 'the loop' has closed (i.e. after the main endwhile). This has solved issues for me in the past
<?php
// custom pagination improvements
//http://codex.wordpress.org/Template_Tags/get_posts
$lastposts = get_posts('numberposts=50&order=DESC&orderby=ID');
setup_postdata($lastposts);
$valid_posts = array ();
$lastposts = (array) $lastposts;
foreach ($lastposts as $post) {
$post = (array) $post;
// Sort through arrays here - get the next valid post
switch (true) {
case ($post['post_status'] == 'publish' && $post['ID'] < $curr_pid[0]):
array_push($valid_posts, $post);
break;
default:
break;
}
}
$nextArray = $valid_posts[0];
?>
<ul class="pagination">
<li class="next"><?php echo ($nextArray['post_title']); ?></li>
</ul>
This is some code I wrote for the front page so it would just show "next", and then link to the next post according to my filter (rather than what Wordpress thought should go next). You could of course echo out multiple links with numbers using a foreach loop. This will complicate thing a little, but it gives you very granular control over what is happening in the pagination.
Does that help you?

Categories