Your approach is on the right track, but there are a couple of adjustments needed to make it work as intended. The primary issue is with the scope and updating of the $last_value variable. It needs to be declared outside of the loop to maintain its state across iterations. Here’s a revised version of your code with explanations:
// Initialize the last_value before the loop starts
$last_value = null;
while ( $custom_posts->have_posts() ) :
$custom_posts->the_post();
$post_id = get_the_id();
$meta_field = get_field('my_meta_key', $post_id); // Use get_field instead of get_field_object if you only need the value
// Check if this post's meta value is different from the last one
if ($last_value !== $meta_field) {
// If this isn't the first iteration, close the previous list
if ($last_value !== null) {
echo '</ul>';
}
// Start a new section with the new meta value
echo '<h2>' . esc_html($meta_field) . '</h2>';
echo '<ul>';
// Update last_value to the current meta value
$last_value = $meta_field;
}
// List posts with this meta value
echo '<li><a href="' . esc_url(get_permalink()) . '">' . esc_html(get_the_title()) . '</a></li>';
endwhile;
// Close the last ul if there were any posts
if ($last_value !== null) {
echo '</ul>';
}
wp_reset_postdata();
Key Changes and Explanations:
Scope of $last_value: It’s initialized before the loop begins. This way, it retains its value from one iteration of the loop to the next.
Comparing $last_value: The comparison uses the strict !== operator to avoid issues where PHP might consider different types as equal (e.g., 0 == null).
Escaping Output: esc_html() is used for the title and meta field, and esc_url() for the permalink. This is good practice to prevent XSS attacks.
Closing the Last List: After the loop, there’s a check to close the last if it’s open. This ensures that the HTML structure is properly closed.
Simplifying get_field: If you only need the value of the meta field, get_field() is simpler than get_field_object().
This approach avoids multiple queries and loops, keeping your code efficient and easy to maintain. It dynamically creates sections based on the meta values while iterating through the posts in a single loop.