have_rows()

Description

This function checks to see if a field (such as a Repeater or Flexible Content field) has any rows of data to loop over. This is a boolean function, meaning it returns either true or false.

This function is intended to be used in conjunction with the_row() to step through available values.

Using have_rows() together with the_row() is intended to feel native much like the have_posts() and the_post() WordPress functions.

Change Log

  • Added in version 4.3.0

Parameters

<?php have_rows($field_name, $post_id); ?>
  • $field_name: the name of the repeater / flexible content field to loop through. eg “gallery_images” (required)
  • $post_id: Specific post ID where your value was entered. Defaults to current post ID (not required). This can also be options / taxonomies / users / etc

Usage

Basic loop

if( have_rows('parent_field') ):

    while ( have_rows('parent_field') ) : the_row();

        // Your loop code
        the_sub_field('sub_field');

    endwhile;

else :

    // no rows found

endif;

Repeater field loop

<?php if( have_rows('repeater') ): ?>

	<ul class="slides">

	<?php while( have_rows('repeater') ): the_row(); 

		$image = get_sub_field('image');

		?>

		<li class="slide">

			<img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt'] ?>" />

		    <p class="caption"><?php the_sub_field('caption'); ?></p>

		</li>

	<?php endwhile; ?>

	</ul>

<?php endif; ?>

Flexible content loop

<?php if( have_rows('flexible_content') ): ?>

	<ul class="slides">

	<?php while( have_rows('flexible_content') ): the_row(); ?>

		<li class="slide">

			<?php if( get_row_layout() == 'image_slide' ): 

				$image = get_sub_field('image');

				?>
				<img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt'] ?>" />

			<?php elseif(get_row_layout() == 'video_slide' ): ?>

				<?php the_sub_field('iframe'); ?>

			<?php endif; ?>

		</li>

	<?php endwhile; ?>

	</ul>

<?php endif; ?>

Nested loop

This example shows a repeater field (locations) which holds some basic title and description data along with another repeater field (staff_members) containing the staff members.

The have_rows function will detect a change in $field_name and instantiate a new loop!

<?php // test loop #1 ?>
<?php if( have_rows('locations') ): ?>

	<div class="locations">

	<?php // start loop #1 ?>
	<?php while( have_rows('locations') ): the_row(); ?>

		<div class="location">

			<h3><?php the_sub_field('title'); ?></h3>
			<p><?php the_sub_field('description'); ?></p>

			<?php // test loop #2 (nested) ?>
			<?php if( have_rows('staff_members') ): ?>

				<ul class="staff-members">

					<?php // start loop #2 (nested) ?>
					<?php while( have_rows('staff_members') ): the_row();

						$image = get_sub_field('image');

						?>
						<li>
							<img src="<?php echo $image['url']; ?>" alt="<?php echo $image['alt'] ?>" />
							<h4><?php the_sub_field('name'); ?></h4>
						</li>

					<?php endwhile; ?>
					<?php // end loop #2 (nested) ?>

				</ul>

			<?php endif; ?>
			<?php // end test #2 (nested) ?>

		</div>

	<?php endwhile; ?>
	<?php // end loop #1 ?>

	</div>

<?php endif; ?>
<?php // end test #1 ?>

Notes

the_row()

Because the have_rows() function does not step through each row by itself, using this function without the_row() will create an infinite loop resulting in a white screen.

Scope

Please be aware that the scope of a have_rows() loop is limited to the current row. This means that any sub field function such as get_sub_field() or the_sub_field() will only find data from the current row, not from parent or child rows.

Related