Support

Account

Home Forums Front-end Issues Nested Post Object Fields

Solved

Nested Post Object Fields

  • So, I’m building an Event listing using ACF, custom post types, and woocommerce.

    On my single event page I’m querying first a Post Object Repeater to select various products/tickets to associate with the event. I get the title of the product, and a couple of other ACF fields just fine. But then on that product/ticket page there is another post object field, referencing a venue custom post type. I’m trying to grab that post object field from my single event page, but not having any luck.

    Here’s my code. Hoping someone can assist. I feel like I’m close, but just missing something fairly obvious. It works up until the venue_object section.

    				if( have_rows('choose_dates')): // check for repeater fields 
    					if( have_rows('choose_dates') ):
    						while ( have_rows('choose_dates') ) : the_row();
    							$post_object = get_sub_field('pick_the_dates');
    								if( $post_object ):
    									$post = $post_object; setup_postdata( $post );
    				?>
    				<div class="container-fluid performances">
    					<div class="row">
    						<div class="col-md-1 col-sm-2 showtime">
    							<a href="<?php the_permalink(); ?>"><span class="list-ticket"><?php the_title(); ?></span></a>
    						</div>
    						
    						<div class="col-md-8 col-sm-8">
    							<?php $venue_object = get_field('event_location', $post_object->ID);
    								if( $venue_object ):
    									$venue = $venue_object;
    									
    									setup_postdata( $venue );
    							?>
    							
    							<p><?php the_field('showtime', $post_object->ID); the_field('am_pm', $post_object->ID); ?> <a href="<?php the_permalink($venue_object->ID); ?>"><?php the_title($venue_object->ID); ?></a>Venue name - City, State</p>
    							
    							<?php wp_reset_postdata( $venue );
    								endif;
    							?>
    							<h6><?php the_field('show_name', $post_object->ID); ?></h6>
    						</div>
    						
    						<div class="col-md-3 col-sm-2">
    							<a class="btn btn-default" href="<?php the_permalink($post_object->ID); ?>">Info & Tickets</a>
    						</div>
    					</div>
    				</div>
    				
    									<?php wp_reset_postdata();
    								endif;
    						endwhile;
    					endif;
    				endif; ?>
  • Try to persist your object->ID always, try something like:

    
    <?php
    if(have_rows('my-repeater', mypostfather->ID) :
    while(have_rows('my-repeater', mypostfather->ID) : the_row();
    $my-son-object = get_sub_field('my-relational-post-object-field'); //return your related-post 
    $my-son-values = get_field('my-son-acf-value', $my-son-object->ID);
    endwhile;endif;
    ?>
    

    I think that your wp_reset_postdata($venue) is causing the problem.
    I don’t use setup_post_data on custom-post-type-objects like $video, $venue, $etc

  • No, this doesn’t seem to be working. The section of the code in question (venue) that’s not working isn’t a repeater in this case. It’s simply a post_object.

  • I’m going to try to help you by explaining what the problem with your code is. This comes up often because most people don’t understand how wp_reset_post_data() really works.

    
     
      // this is inside the main WP query loop or "The Loop"
      
      // some time later
      
                  $post_object = get_sub_field('pick_the_dates');
                    if( $post_object ):
                      $post = $post_object; setup_postdata( $post );
                      
      // some time later
                    if( $venue_object ):
                      $venue = $venue_object;
                      
                      setup_postdata( $venue );
                      
      // some time later, 
      // this is the problem.
      // wp_reset_post_data does not take any arguments
      // this function, no matter how you call it will always
      // reset post data to "The Main Query"
      // once you do this, any reference to the post 
      // object returned by get_sub_field('pick_the_dates') 
      // will be looking at the post of the main query instead
      // of what you think you are looking at
      // in order to have multiple nestings you must use 
      // alternate means of getting values
      // other than using setup_postdata and wp_reset_postdata
                      
                      wp_reset_postdata( $venue );
                      
      // some time later
      // this next line actually does nothing 
      // because it was already done above
            
                      wp_reset_postdata();
    
  • Thank you. This actually helped a lot. I’ve got it working correctly now. Much appreciated 🙂

  • Hi @brotsky_pixie are you please able to detail how you fixed the issue?

    Thanks

  • I’m struggling with this as well.

    • goto11

    • February 28, 2019 at 2:26 am

    Me too. I have a multiple Post Objects field, that then needs to display a single Post Object attached to each of those. @jamieics we are late to the party here, but did you get anywhere?!

  • @goto11 Unfortunately, I didn’t. I ended up moving the nested Post Object to a repeater instead. Not ideal for my situation, but timing was tight.

    • goto11

    • February 28, 2019 at 2:59 am

    @jamieics no worries, I was starting to think I would need to do the same! Likewise time is tight, so I’ll crack on. Thanks for the reply

  • The examples on this site are for the simplest use of each field so do not cover the nuances of nested post loops. This all comes down to understanding what I explained above, that wp_reset_postdata() always resets the global $post variable to the main query’s post and not to the previous query’s post. This is something that is not explained well in the WP documentation. Every case of nested post queries will be a little different, however, the same principle applies. When you have nested queries you cannot use setup_postdata($posts) and wp_reset_postdata();

    Instead you must do the work yourself rather than relying on WP to do the work for you. A quick example of showing the title for posts in a relationship field.

    
    $related_posts = get_field('my-relationship-field');
    if ($related_posts) {
      foreach ($related_posts as $related_post) {
        ?><h1><?php echo get_the_title($related_post->ID); ?></h1><?php 
      }
    }
    

    This could also be done like this

    
    $related_posts = get_field('my-relationship-field');
    if ($related_posts) {
      foreach ($related_posts as $related_post) {
        ?><h1><?php echo $related_post->post_title ?></h1><?php 
      }
    }
    

    Getting fields from a related post

    
    $related_posts = get_field('my-relationship-field');
    if ($related_posts) {
      foreach ($related_posts as $related_post) {
        $some_value = get_field('some-field', $related_post->ID);
      }
    }
    
    • goto11

    • March 2, 2019 at 12:38 am

    @hube2 Many thanks for the further input.

    At first glance I couldn’t see anything in your notes that I hadn’t tried. Then I noticed that you were referring to using a nested Relationship field instead of nested Post Object fields and the penny dropped for how I should be solving this. As Post Objects seem to only work using $post, your code was obviously not working. Switching to using a Relationship field instead, and using your suggested code is now working just great.

    I just need to remember for future instances that Relationship fields should be the way to go instead of Post Objects for most uses, as they are able to use their own separate query, without getting thrown by being forced to use the main setup_postdata($posts) query.

    I’ve probably worded all that horribly, but hopefully you get the idea! Thanks to all for the help!

  • Post object fields and relationship fields work the same way except for one difference. If a post object field only allows one selection then it will only return a single post, so you don’t need a loop.

    
    $related_post = get_field('my-post-object-field');
    if ($related_post) {
      ?><h1><?php echo get_the_title($related_post->ID); ?></h1><?php 
    }
    
    • jnicol

    • June 14, 2019 at 11:50 am

    I think it is possible to nest setup_postdata() while also avoiding multiple calls to wp_reset_postdata(). This can be achieved by storing the post object that you want to revert to in a variable, and later running setup_postdata() on it.

    Untested code to demonstrate:

    // Inside the main loop.
    
    // Setup outer post object.
    // Store it in $outer_post_object so that we can revert to it later.
    $outer_post_object = get_field('my_field');
    $post = $outer_post_object; // override $post
    setup_postdata($post);
    
    // Later on, setup an inner post object
    $inner_post_object = get_field('my_sub_field');
    $post = $inner_post_object; // override $post
    setup_postdata($post);
    
    // Later on, when you want to revert to $outer_post_object
    // Instead of wp_reset_postdata(), do this:
    $post = $outer_post_object;
    setup_postdata($post);

    Using this technique you can have as many nested setup_postdata() as you like.

  • Yes it is and it can work. I posted an example of this hack here https://support.advancedcustomfields.com/forums/topic/hack-for-nested-queries/

    • jnicol

    • June 17, 2019 at 10:56 am

    I knew you’d be across it, John!

    Though I’m not sure I would call it a hack. It seems cleaner than having to explicitly pass an ID to every call to the_field/get_field?

    Speaking of which, I just ran across a similar problem when using ACF Post Objects inside ACF Gutenberg Block render templates:

    https://support.advancedcustomfields.com/forums/topic/post-objects-setup_postdata-and-get_field-in-acf-blocks/

    I am interested to know if this is something you’ve come across before John?

  • Going to be honest with you, I have no idea. I have made the decision that I will not be using the block editor for the foreseeable future. Frankly, it’s not what my clients want or need for various reasons. I am working towards not allowing the default editor and new themes that I’m building are replacing the default WP editor with an ACF WYSIWYG field in all cases. Having made this decision I have not even looked at ACF blocks. It also means that I may need to pull one of my plugins off of the WP repo.

Viewing 17 posts - 1 through 17 (of 17 total)

You must be logged in to reply to this topic.

We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.