-
Notifications
You must be signed in to change notification settings - Fork 262
each_connected
Continuing from the Basic usage tutorial, let's say that you want to display the connected pages, not just for a single post, but for all posts in an archive.
You could just copy the code you used for a single post:
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
<?php the_title(); ?>
<?php
// Find connected pages
$connected = new WP_Query( array(
'connected_type' => 'posts_to_pages',
'connected_items' => $post,
'nopaging' => true
) );
// Display connected pages
echo '<p>Related pages:</p>';
while ( $connected->have_posts() ) : $connected->the_post();
the_title();
echo '<p>Connection ID: ' . $post->p2p_id . '</p>';
...
endwhile;
wp_reset_postdata(); // set $post back to original post
?>
<?php endwhile; ?>
The only change I made was replacing get_queried_object()
with $post
.
This will work as expected, but you're making at least one additional SQL query for each post. If you have 10 or 20 posts per page, that's a lot of extra queries!
On each request, WordPress automatically runs a query which finds the appropriate posts to display. These posts are stored in the $wp_query
global variable. That's where The Loop pulls it's data from.
Since we already have all the posts tucked away in $wp_query, couldn't we find all the connected pages for all the posts in one go?
Here's how that would look like:
<?php
// Find connected pages (for all posts)
p2p_type( 'posts_to_pages' )->each_connected( $wp_query );
?>
<?php while ( $wp_query->have_posts() ) : $wp_query->the_post(); ?>
<?php the_title(); ?>
<?php
// Display connected pages
echo '<p>Related pages:</p>';
foreach ( $post->connected as $post ) : setup_postdata( $post );
the_title();
echo '<p>Connection ID: ' . $post->p2p_id . '</p>';
...
endforeach;
wp_reset_postdata(); // set $post back to original post
?>
<?php endwhile; ?>
p2p_type( 'posts_to_pages' )->each_connected()
runs a single query, which is much more efficient.
The only other difference is that instead of looping over $connected
, we loop over $post->connected
.
You can use each_connected() on custom queries and multiple times on the same query:
<?php
$my_query = new WP_Query( array(
'post_type' => 'movie'
) );
p2p_type( 'movies_to_actors' )->each_connected( $my_query, array(), 'actors' );
p2p_type( 'movies_to_locations' )->each_connected( $my_query, array(), 'locations' );
while ( $my_query->have_posts() ) : $my_query->the_post(); ?>
<?php the_title(); ?>
<?php
// Display connected actors
echo '<p>Actors:</p>';
foreach ( $post->actors as $post ) : setup_postdata( $post );
the_title();
...
endforeach;
wp_reset_postdata();
// Display connected locations
echo '<p>Filming locations:</p>';
foreach ( $post->locations as $post ) : setup_postdata( $post );
the_title();
...
endforeach;
wp_reset_postdata();
?>
<?php endwhile; ?>
Since P2P 1.3, you can use each_connected()
with an array of post objects as well:
<?php
$my_query = new WP_Query( array(
'post_type' => 'movie'
) );
p2p_type( 'movies_to_actors' )->each_connected( $my_query, array(), 'actors' );
while ( $my_query->have_posts() ) : $my_query->the_post();
// Another level of nesting
p2p_type( 'actors_to_producers' )->each_connected( $post->actors, array(), 'producers' );
foreach ( $post->actors as $post ) : setup_postdata( $post );
echo '<h3>Connected Producers</h3>';
foreach ( $post->producers as $post ) : setup_postdata( $post );
the_title();
...
endforeach;
endforeach;
wp_reset_postdata();
endwhile;
You might also want to read about p2p_distribute_connected().