acf-extended / ACF-Extended

🚀 All-in-one enhancement suite that improves WordPress & Advanced Custom Fields
https://www.acf-extended.com
239 stars 27 forks source link

Flexible content field. Global post variable in field "Relationship". #100

Closed Danil-Klimov closed 1 year ago

Danil-Klimov commented 2 years ago

Describe the bug I am using a flexible content field. In this field I use relationship field. When i display this field in the frontend, the global variable ($post) is not set. Instead of the post title, the title of the current page is displayed for the entire set of posts.

To Reproduce

Expected behavior Posts displaying properly.

Screenshots image image image

<?php $products = get_sub_field('products'); ?>
<?php if($products) : ?>
  <?php foreach ($products as $post) : setup_postdata($post); ?>
    <p><?php the_title(); ?></p>
  <?php endforeach; wp_reset_postdata(); ?>
<?php endif; ?>

WordPress & ACF WordPress version: 6.0 ACF Pro version: 5.12.2 ACF add-ons: ACF Extended 0.8.8.6

acf-extended commented 1 year ago

Hello,

Thanks for the feedback, and sorry for the late answer.

When using the Flexible Content Dynamic Render/Preview, you're rendering your layout template from a function: the_flexible().

In order to use the wp $post variable (used by setup_postdata() & wp_reset_postdata()), you have to add a global $post in your PHP code, so it is scoped inside the function. Usage example:

<?php 
global $post;
$products = get_sub_field('products'); ?>
<?php if($products) : ?>
    <?php foreach ($products as $post) : setup_postdata($post); ?>
        <p><?php the_title(); ?></p>
    <?php endforeach; wp_reset_postdata(); ?>
<?php endif; ?>

To avoid using that global $post, you could generate a new WP_Query() using the sub field value post ids, as $query->the_post() already does the global $post. Usage example:

<?php 
// use format_value = false to only get post ids
$products = get_sub_field('products', false); ?>

<?php
$query = new WP_Query(array(
    'post_type' => 'any',
    'post__in'  => $products,
    'orderby'   => 'post__in',
    'nopaging'  => true,
));
?>

<?php if($query->have_posts()): ?>
    <?php while($query->have_posts()): $query->the_post(); ?>
        <p><?php the_title(); ?></p>
    <?php endwhile; wp_reset_postdata(); ?>
<?php endif; ?>

Hope it helps!

Have a nice day!

Regards.