WordPress.org

Make WordPress Core

Opened 7 years ago

Closed 7 years ago

#24785 closed enhancement (fixed)

Nested loops and resetting post data

Reported by: ericlewis Owned by: nacin
Milestone: 3.7 Priority: normal
Severity: normal Version:
Component: Query Keywords: has-patch needs-testing has-unit-tests
Focuses: Cc:

Description

While building a custom loop, developers currently only have one function to reset post data - wp_reset_postdata(). This function resets the $post globals and thereby template tags to the original queried object in the $wp_query global. That's great, but not when it comes to nested loops. Using this function when you're deep within a nest of custom loops would mean upon exiting a loop, calling this function resets to the original queried object, although you're still within a loop that has posts related to it.

Attachments (6)

24785.diff (607 bytes) - added by ericlewis 7 years ago.
24785.1.diff (584 bytes) - added by ericlewis 7 years ago.
remove incorrect doc block reference to introduction in 3.3
24785.2.diff (577 bytes) - added by ericlewis 7 years ago.
Remove namespacing on the wp_reset_postdata() function, rename to reset_postdata
24785.3.diff (578 bytes) - added by wonderboymusic 7 years ago.
24785.unit-tests.diff (924 bytes) - added by ericlewis 7 years ago.
24785.4.diff (1.7 KB) - added by ericlewis 7 years ago.

Download all attachments as: .zip

Change History (16)

@ericlewis
7 years ago

#1 @ericlewis
7 years ago

In attachment:24785.diff, I suggest we copy the function wp_reset_postdata into a method to the WP_Query class, so upon exiting a nested loop, this method can be called on the previous query object. A la:

<?php /* The loop */ ?>
<?php while ( have_posts() ) : the_post(); ?>
	<?php
	// Build custom query
	$query = new WP_Query( array(
		'posts_per_page' => 1
	) );
	// Custom query loop
	if ( $query->have_posts() ) {
		while ( $query->have_posts() ) {
			$query->the_post();
			// Build nested custom query
			$subquery = new WP_Query( array(
				'posts_per_page' => 2
			) );
			// Nested custom query loop
			if ( $subquery->have_posts() ) {
				while ( $subquery->have_posts() ) {
					$subquery->the_post();
					echo '<li>' . get_the_title() . '</li>';
				}
			} else {
				// no posts found
			}
			/* Restore custom query's post data */
			$query->wp_reset_postdata();
			echo '<li>' . get_the_title() . '</li>';
		}
	} else {
		// no posts found
	}

	/* Restore original Post Data */
	wp_reset_postdata(); ?>

<?php endwhile; ?>

@ericlewis
7 years ago

remove incorrect doc block reference to introduction in 3.3

#2 @ericlewis
7 years ago

  • Keywords has-patch dev-feedback added

@ericlewis
7 years ago

Remove namespacing on the wp_reset_postdata() function, rename to reset_postdata

#3 @johnbillion
7 years ago

  • Cc johnbillion added

#4 @swissspidy
7 years ago

  • Cc hello@… added

#5 @wonderboymusic
7 years ago

  • Keywords needs-testing needs-unit-tests added; dev-feedback removed
  • Milestone changed from Awaiting Review to 3.7

.3.diff rehabilitates the whitespace

#6 @nacin
7 years ago

Is this something we write do a unit test for?

#7 @ericlewis
7 years ago

  • Keywords has-unit-tests added; needs-unit-tests removed

attachment:24785.unit-tests.diff includes a unit test for postdata resetting while exiting a nested loop.

#8 follow-up: @nacin
7 years ago

Cool, I like this. Let's have wp_reset_postdata() call this method, then.

@ericlewis
7 years ago

#9 in reply to: ↑ 8 @ericlewis
7 years ago

attachment:24785.4.diff makes wp_reset_postdata() call reset_postdata() on the global $wp_query, as well as combining the unit test and the core patch into one.

#10 @nacin
7 years ago

  • Owner set to nacin
  • Resolution set to fixed
  • Status changed from new to closed

In 25601:

Introduce a reset_postdata() method on the WP_Query object, which wp_reset_postdata() now wraps.

props ericlewis.
fixes #24785.

Note: See TracTickets for help on using tickets.