Support

Account

Home Forums ACF PRO if (have_rows()) not working

Solving

if (have_rows()) not working

  • if(have_rows()): has completely stopped working for me after updating to 5.1.1… It not always returns true, even though it’s supposed to be false.

    while(have_rows()): seem to work though.

  • I am having this issue as well.

  • I’ve rolled back to 5.1.0 in the meantime. This bug made things look messed up 😛

  • Same here!

    I notice a recent behaviour change, that probably happened with the latest ACF Pro update.

    On WordPress instances where I used Repeater Fields with this type of code:

    if( have_rows('acf_repeater_field') ):
        while ( have_rows('acf_repeater_field') ) : the_row();
            // OUTPUT
        endwhile;
    endif;

    Until now, when no fields where present, there was no output.

    What I see now: even when there are no fields, there’s an output – html markup is generated. If I dump the raw content of the acf_repeater_field, I see a NULL array.

    So my quick fix is to surround the whole block of code with something like:

    $acf_repeater_field = get_field('acf_repeater_field');
        if ( !empty( $acf_repeater_field ) ) :
        // ETC
    endif;

    Any explanation for this behavior? Is it indeed a change in ACF?

  • I have a similar issue having just updated to 5.1.1. I have a banner gallery assigned to every page using a Repeater Field with a fallback to the gallery assigned to the home page if no images have been uploaded to the individual page.

    If I add and then delete images from a page gallery (have_rows()) appears to still be returning true even though images are no longer assigned to the page and I’ve removed the row(s) from the admin area (and saved the page), so I get no fallback banner gallery output on the pages.

    echo '<div id="banner">';
    	if( have_rows('banner_gallery')){
    	while( have_rows('banner_gallery') ): the_row();
    		$image = wp_get_attachment_image_src(get_sub_field('banner_image'), 'bannerwide-image');
    			echo '<img src="'.$image[0].'"  />';
    	endwhile;
    	} else {  // show the gallery images assigned to home page (ID 2)
    	while( have_rows('banner_gallery',2)): the_row();
    		$image = wp_get_attachment_image_src(get_sub_field('banner_image'), 'bannerwide-image');
    			echo '<img src="'.$image[0].'" />';
    	endwhile;
    	}
    echo '</div>';
  • Hi guys

    Thanks for the bug report. I’ve found and fixed the issue. You can expect an update shortly, but for now, please find and replace the have_rows() function within the api-template.php file:

    
    /*
    *  have_rows
    *
    *  This function will instantiate a global variable containing the rows of a repeater or flexible content field,
    *  afterwhich, it will determin if another row exists to loop through
    *
    *  @type	function
    *  @date	2/09/13
    *  @since	4.3.0
    *
    *  @param	$field_name (string) the field name
    *  @param	$post_id (mixed) the post_id of which the value is saved against
    *  @return	(boolean)
    */
    
    function have_rows( $selector, $post_id = false ) {
    	
    	// vars
    	$row = array();
    	$new_parent_loop = false;
    	$new_child_loop = false;
    	$sub_field = false;
    	$sub_exists = false;
    	
    	
    	// reference
    	$_post_id = $post_id;
    	
    	
    	// filter post_id
    	$post_id = acf_get_valid_post_id( $post_id );
    	
    	
    	// empty?
    	if( empty($GLOBALS['acf_field']) ) {
    		
    		// reset
    		reset_rows( true );
    		
    		
    		// create a new loop
    		$new_parent_loop = true;
    	
    	} else {
    		
    		// vars
    		$row = end( $GLOBALS['acf_field'] );
    		$prev = prev( $GLOBALS['acf_field'] );
    		$change = false;
    		
    		
    		// detect change
    		if( $post_id != $row['post_id'] ) {
    			
    			$change = 'post_id';
    				
    		} elseif( $selector != $row['selector'] ) {
    			
    			$change = 'selector';
    				
    		}
    		
    		
    		// attempt to find sub field
    		if( $change ) {
    			
    			$sub_field = acf_get_sub_field($selector, $row['field']);
    			
    			if( $sub_field ) {
    				
    				$sub_exists = isset($row['value'][ $row['i'] ][ $sub_field['key'] ]);
    				
    			}
    			
    		}
    		
    		
    		// If post_id has changed, this is most likely an archive loop
    		if( $change == 'post_id' ) {
    			
    			if( $prev && $prev['post_id'] == $post_id ) {
    				
    				// case: Change in $post_id was due to a nested loop ending
    				// action: move up one level through the loops
    				reset_rows();
    			
    			} elseif( empty($_post_id) && $sub_exists ) {
    				
    				// case: Change in $post_id was due to this being a nested loop and not specifying the $post_id
    				// action: move down one level into a new loop
    				$new_child_loop = true;
    			
    			} else {
    				
    				// case: Chang in $post_id is the most obvious, used in an WP_Query loop with multiple $post objects
    				// action: leave this current loop alone and create a new parent loop
    				$new_parent_loop = true;
    				
    			}
    			
    		} elseif( $change == 'selector' ) {
    			
    			if( $prev && $prev['selector'] == $selector && $prev['post_id'] == $post_id ) {
    				
    				// case: Change in $field_name was due to a nested loop ending
    				// action: move up one level through the loops
    				reset_rows();
    				
    			} elseif( $sub_exists ) {
    				
    				// case: Change in $field_name was due to this being a nested loop
    				// action: move down one level into a new loop
    				$new_child_loop = true;
    				
    			} else {
    				
    				// case: Chang in $field_name is the most obvious, this is a new loop for a different field within the $post
    				// action: leave this current loop alone and create a new parent loop
    				$new_parent_loop = true;
    				
    			}
    			
    		}
    		
    	}
    	
    	
    	if( $new_parent_loop ) {
    		
    		// vars
    		$field = get_field_object( $selector, $post_id, false );
    		$value = acf_extract_var( $field, 'value' );
    		
    		
    		// add row
    		$GLOBALS['acf_field'][] = array(
    			'selector'	=> $selector,
    			'value'		=> $value,
    			'field'		=> $field,
    			'i'			=> -1,
    			'post_id'	=> $post_id,
    		);
    		
    	} elseif( $new_child_loop ) {
    		
    		// vars
    		$value = $row['value'][ $row['i'] ][ $sub_field['key'] ];
    		
    		$GLOBALS['acf_field'][] = array(
    			'selector'	=> $selector,
    			'value'		=> $value,
    			'field'		=> $sub_field,
    			'i'			=> -1,
    			'post_id'	=> $post_id,
    		);
    		
    	}	
    	
    	
    	// update vars
    	$row = end( $GLOBALS['acf_field'] );
    	
    	
    	
    	// return true if next row exists
    	if( is_array($row['value']) && array_key_exists($row['i']+1, $row['value']) ) {
    		
    		return true;
    		
    	}
    	
    	
    	// no next row!
    	reset_rows();
    	
    	
    	// return
    	return false;
      
    }
    

    Please let me know how this fix goes

  • Update: Just released ACF PRO 5.1.2 – fixes have_rows() issues

    Please let me know if your issues are resolved after updating

  • I’m still experiencing issues in 5.1.2 with the repeater field. If I try and assign a row to an array, previously the key would be the name of the field and the value would be the contents. Now instead of the field name I’m getting keys like ‘field_544dbdc0e5e88’. I’ve also assigned one of the repeater subfields to return an image URL, but instead it’s returning the image ID.

  • Hi @ankhou

    Yes, the recent changes to the_row() now store the unformulated value in the global variable.

    Previously, this global variable should contain the formatted value, but this change was necessary to allow for the new $format_value parameter in the get_sub_field function.

    I advise not to use the returned array from the_row, but instead to use get_sub_field function for any sub field value.

    Thanks
    E

  • Thanks for the clarification Elliot, I’ve taken your advice.

  • I still have the same problem.

  • I am recently having this issue as well. Has this cropped back up possibly again?
    Code is exactly like ms-studio’s example.

  • Wordpress 4.3.1, ACF 5.3.2 not work this code
    if (have_rows('field','option')){}
    Why is that?

  • Hi Elliot,

    I’d just like to chime in and say that have_rows doesn’t seem to generate any output on the front-end when used within an Options page (the field data is stored just fine in the database though).

    I’ve tried your api-template.php hotfix, but sadly, that doesn’t seem to have done the trick 🙁

    For the sake of reference, I am running WP 4.3.1 and ACF Pro latest.

  • Yep, doesn’t work for me as well. If all fields are empty it still generates HTML markup to hold the content. Running latest version of both.

    *edit: Actually just looking into this more, it only seems to be with Repeater fields. Is that the case for anyone else?

    Code examples:

    This works:

    <?php if(get_field("cabinet_or_party_leader")) : ?>
        <p class="cabinet-or-party"><span><?php the_field( "cabinet_or_party_leader" ); ?></span></p>
      <?php endif; ?>

    This doesn’t work:

    <?php
              if(have_rows('family_information')) : ?>
              <hr>
              <h4>Family</h4>
              <table class="info-table">
                <tbody>
                  <?php while( have_rows('family_information') ): the_row() ; ?>
                    <?php if(get_sub_field('marital_status')) : ?>
                      <tr>
                        <td class="title">Marital Status:</td>
                        <td><?php the_sub_field('marital_status') ?></td>
                      </tr>
                    <?php endif; ?>
                    <?php if(get_sub_field('spouse_name')) : ?>
                      <tr>
                        <td class="title">Spouse Name:</td>
                        <td><?php the_sub_field('spouse_name') ?></td>
                      </tr>
                    <?php endif; ?>
                    <?php if(get_sub_field('spouse_occupation')) : ?>
                      <tr>
                        <td class="title">Spouse Occupation:</td>
                        <td><?php the_sub_field('spouse_occupation') ?></td>
                      </tr>
                    <?php endif; ?>
                    <?php if(get_sub_field('children')) : ?>
                      <tr>
                        <td class="title">Children:</td>
                        <td>
                          <ul class="blank-list">
                            <?php while( have_rows('children_details') ): the_row() ; ?>
                              <li>
                                <?php if(get_sub_field('child_name')) the_sub_field('child_name') ?><?php if(get_sub_field('child_name') && get_sub_field('child_age') || get_sub_field('note')) echo ', ' ?><?php if(get_sub_field('child_age')) echo get_sub_field('child_age') ?><?php if(get_sub_field('child_age') && get_sub_field('note')) echo ', ' ?><?php if(get_sub_field('note')) the_sub_field('note') ?>
                              </li>
                            <?php endwhile; ?>
                          </ul>
                        </td>
                      </tr>
                    <?php endif; ?>
                    <?php if(get_sub_field('relations')) : ?>
                      <tr>
                        <td class="title">Relations:</td>
                        <td>
                          <ul class="blank-list">
                            <?php while( have_rows('relations_details') ): the_row() ; ?>
                              <li>
                                <?php if(get_sub_field('relation_name')) the_sub_field('relation_name') ?><?php if(get_sub_field('relation_name') && get_sub_field('relation_age') || get_sub_field('note')) echo ', ' ?><?php if(get_sub_field('relation_age')) the_sub_field('relation_age') ?><?php if(get_sub_field('relation_age') && get_sub_field('note')) echo ', ' ?><?php if(get_sub_field('note')) the_sub_field('note') ?>
                              </li>
                            <?php endwhile; ?>
                          </ul>
                        </td>
                      </tr>
                    <?php endif; ?>
                  <?php endwhile; ?>
                </tbody>
              </table>
            <?php endif; ?>

    and still outputs this html:

    <h4>Family</h4>
    <table class="info-table">
                <tbody>
                                                                                                                            </tbody>
              </table>
  • Options Page with a Repeater field is not working – doing a get_field(‘repeaterfield’,’option’); returns the number of rows instead of the usual array of sub-fields. have_rows(‘repeaterfield’, ‘option’) while or ifs do not work at all. This appears to be a bug.

  • With the latest version I’m finding some posts would return nothing for have_rows when others would work fine.

    It seems that if multiple have_rows calls are made to the same field for some reason within the page load logic, it doesn’t always work. Looking into it more.

  • Im seeing the same behavior as @bkno – hope to see a fix soon 🙁
    Im Running WordPress 4.3.1 + ACFP Version 5.3.2.2

  • No news around this?

  • Hi guys

    Elliot here (ACF dev)

    I’m not able to replicate any have_rows issues on my local site, so there must be something else which can explain the problem.

    Can you please provide WP and FTP access for me to do some testing?
    Please email our support team directly with this info: [email protected]

    Please be sure to include a link to this thread within the email and ask for the ticket to be forwarded to ‘Elliot’ as he has requested.

    Thanks
    E

  • Hi Elliot,

    I’m also having what seems to be a similar issue.

    The setup is the following:
    – I have a Flexible Content field called “gallery”.
    – On the homepage I call have_rows(“gallery”) to show the gallery associated to the homepage.
    – I now want to have a separate div for the mobile version of the site which shows the first gallery field for each project (I’ve setup a custom post type called “work”). I use a custom WP_Query to get the required posts of the homepage. This works as expected, but if I then use have_rows(“gallery”) within the WP_Query this seems to completely break WordPress, the page never actually loads, it’s probably stuck in some sort of redirect.

    Here is one error from the PHP log:
    [10-Dec-2015 18:11:29 UTC] PHP Fatal error: Maximum execution time of 30 seconds exceeded in /Volumes/Date/Dropbox/htdocs/blid/wp-content/plugins/advanced-custom-fields-pro/api/api-template.php on line 552

    (the code line varies from what I’ve seen logged)

    Does this help in explaining the problem?

    Thanks,
    Tudor

  • Hi Elliott,

    I am also having this problem with if(have_rows…..

    I am on version 5.3.0 – I know there is a more current update, but right now I’m not able to update because we are working through troubleshooting some plugin conficts that started occurring after I recently updated several, including ACF – I had to roll back on all of them (including ACF, to 5.3.0) until I figure out the problem.

    Right now when I use if(have_rows on a post and there is no data for that repeater field attached to that post, it is still follows the code and outputs the HTML that it should not output….I tried the suggestion made by @ms-studio over a year ago of wrapping my code in something similar to this:

    $acf_repeater_field = get_field(‘acf_repeater_field’);
    if ( !empty( $acf_repeater_field ) ) :
    // ETC
    endif;

    But that doesn’t work. Was this problem fixed in the most current update? Is there a different workaround I can use until I can update?

  • In looking at wp_postmeta via phpMyAdmin, I see that for the Post in question (where I have nothing entered in the repeater field but the HTML is still being displayed), there is actually a ‘1’ in the database…..? If I haven’t entered anything into the field when adding/editing a post, why is a ‘1’ being saved to the database? I could understand a ‘0’ or ‘null’, both of which could be returned as false for a boolean ‘if’ test, but ‘1’ returns true, which means even if no data is entered the field is never ’empty’.

    Any chance this could get changed in an update so that it either saves nothing to the database (seems like this should be the preference) or if something must be saved, either null or 0?

  • hello, i have the same issue, is there a workaround for this?

  • Hi @dunkel My workaround is this:

    In the Field Group I’m using I NOW have the “Minimum Rows” set to zero, so that NO rows are created by default…..when I’m creating a post and I want to ADD rows, then I use the Add Row Button. Often times I don’t.

    If you leave the “Minimum Rows” setting to it’s default (which I think, at least in my version, is 1) then a single row is created for every Post to which the Field Group is applied – this single empty row is what creates the problem and setting the Minimum Rows to 0 fixes that – no row is created hence there is not a ‘1’ applied to the Post in the database (if you have a single row created by a 1 in the field group’s minimum rows setting, even if it’s empty, it appears in the database and if(have_rows) sees it and counts it).

    By changing that to zero, if you’re using the if(have_rows) you will truly have no rows and the code works…..it only finds rows that you manually added.

    I hope this makes sense!

Viewing 25 posts - 1 through 25 (of 32 total)

The topic ‘if (have_rows()) not working’ is closed to new replies.