Home › Forums › Front-end Issues › 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 🙂
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.
@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);
}
}
@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
}
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/
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:
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.
I have a question on this topic. I have three post types. Notebooks -> Notebook Sections -> Notebook Pages. I have added two post object fields to the notebook pages. The first one picks the notebook the page goes into and I want the second one to only pull up the notebook sections that are children of the notebook selected. I also have a post object field on the notebook sections to choose the notebook parent to attach it to. This is the code I am using in my functions.php for that one.
function my_acf_save_post( $post_id ) {
// Get the selected post status
$value = get_field('notebook_section_post_parent', $post_id);
// Update current post
$post = array(
'ID' => $post_id,
'post_parent' => $value,
);
// Remove the action to avoid infinite loop
remove_action('acf/save_post', 'my_acf_save_post', 20);
// Update the post into the database
wp_update_post( $post );
// Add the action back
add_action('acf/save_post', 'my_acf_save_post', 20);
}
// run after ACF saves the $_POST['acf'] data
add_action('acf/save_post', 'my_acf_save_post', 20);
So, how do I make the notebook section field on the notebook pages only pull up the children of the notebook selected? I’m really new to coding, so I just can’t wrap my head around it and how to do it without it all getting so complicated. I appreciate ANY advice. Thanks!
The topic ‘Nested Post Object Fields’ is closed to new replies.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
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 Privacy Policy. If you continue to use this site, you consent to our use of cookies.