Skip to content

Looping The Loop

scribu edited this page May 24, 2011 · 23 revisions

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.

The slow way

You could just copy the code you used for a single post:

<?php while ( have_posts() ) : the_post(); ?>

<!-- Some standard stuff here, like the_title(); etc. -->

<?php
	// Find connected pages
	$connected = new WP_Query( array(
		'post_type' => 'page',
		'connected_from' => $post->ID
	) );

	// Display connected pages
	echo '<p>Related pages:</p>';
	echo '<ul>';
	while ( $connected->have_posts() ) : $connected->the_post();
		echo '<li>';
		the_title();
		echo '</li>';
	endwhile;
	echo '</ul>';

	// Prevent weirdness
	wp_reset_postdata();
?>

<?php endwhile; ?>

The only change I made was replacing get_queried_object_id() with $post->ID.

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!

Using p2p_each_connected()

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_each_connected( $wp_query, array(
	'post_type' => 'page',
) );
?>

<?php while ( have_posts() ) : the_post(); ?>

<!-- Some standard stuff here, like the_title(); etc. -->

<?php
	// Display connected pages
	echo '<p>Related pages:</p>';
	echo '<ul>';
	foreach ( $post->connected as $post ) {
		setup_postdata( $post );

		echo '<li>';
		the_title();
		echo '</li>';
	}
	echo '</ul>';

	// Prevent weirdness
	wp_reset_postdata();
?>

<?php endwhile; ?>

p2p_each_connected() runs a single query, which is much more efficient.

The only other difference is that the connected pages are now stored as an array in $post->connected.

Using 'each_connected' query var

If you're creating your own custom loop or are using get_posts(), you can specify an 'each_connected' query var, like so:

<?php
$my_query = new WP_Query( array(
	'ignore_sticky_posts' => true,
	'post_type' => 'post',
	'each_connected' => array(
		'post_type' => 'page',
	)
) );
?>

Then, you would display them, almost exactly as before:

<?php while ( $my_query->have_posts() ) : $my_query->the_post(); ?>

<!-- Some standard stuff here, like the_title(); etc. -->

<?php
	// Display connected pages
	echo '<p>Related pages:</p>';
	echo '<ul>';
	foreach ( $post->connected as $post ) {
		setup_postdata( $post );

		echo '<li>';
		the_title();
		echo '</li>';
	}
	echo '</ul>';

	// Prevent weirdness
	wp_reset_postdata();
?>

<?php endwhile; ?>
Clone this wiki locally