admin管理员组

文章数量:1125978

I have a query, sorted by a meta field, and I am trying to figure out how to split the query into different sections based on the meta field. Essentially I want there to be an h2 and a ul for each different meta value. I would prefer not to make multiple different loops for each meta value, but I can't figure out how to accomplish this, or if it's even possible, within a single loop. Here's what I've tried so far:

while ( $custom_posts->have_posts() ) :
    $custom_posts->the_post();
    $post_id = get_the_id();
    $meta_field = get_field_object('my_meta_key', $post_id); // my custom meta key
    $last_value = null;
    // Start new section if it doesnt exist
    if ($last_value != $meta_field) :
        echo '<h2>'.$meta_field.'</h2>';
        echo '<ul>';
    endif;
    // List posts with this meta value
    echo '<li><a href="'.get_permalink().'">'.get_the_title().'</a></li>';
    // Close section and start anew
    if ($last_value != $meta_field) :
        echo '</ul>';
        // Set last value to most recent meta value
        $last_value = $meta_field;
    endif;
endwhile;
wp_reset_postdata();

I'm hoping that, because the posts are already being returned in the correct order(ie all posts in each meta value are returned sequentially), I can manage to do something similar to this. Is this even possible to do this way? Or is there a better approach?

I have a query, sorted by a meta field, and I am trying to figure out how to split the query into different sections based on the meta field. Essentially I want there to be an h2 and a ul for each different meta value. I would prefer not to make multiple different loops for each meta value, but I can't figure out how to accomplish this, or if it's even possible, within a single loop. Here's what I've tried so far:

while ( $custom_posts->have_posts() ) :
    $custom_posts->the_post();
    $post_id = get_the_id();
    $meta_field = get_field_object('my_meta_key', $post_id); // my custom meta key
    $last_value = null;
    // Start new section if it doesnt exist
    if ($last_value != $meta_field) :
        echo '<h2>'.$meta_field.'</h2>';
        echo '<ul>';
    endif;
    // List posts with this meta value
    echo '<li><a href="'.get_permalink().'">'.get_the_title().'</a></li>';
    // Close section and start anew
    if ($last_value != $meta_field) :
        echo '</ul>';
        // Set last value to most recent meta value
        $last_value = $meta_field;
    endif;
endwhile;
wp_reset_postdata();

I'm hoping that, because the posts are already being returned in the correct order(ie all posts in each meta value are returned sequentially), I can manage to do something similar to this. Is this even possible to do this way? Or is there a better approach?

Share Improve this question asked Jan 25, 2024 at 23:56 user13286user13286 2272 gold badges12 silver badges29 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 1

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.

本文标签: