0

I have a custom post type with 2 custom fields that I am trying to sort by:

  1. The first custom field is "featured post" (yes or no values).
  2. The second custom field is "CPT images published date".

The goal .. to group the posts by

  • "featured post" yes (a max of 3 posts total)
  • and sort them by the published date custom field (DESC order)

THEN

  • "featured post" no (all the rest of the posts)
  • and sort them by the published date custom field (DESC order)

In my results, the first meta_query is working, and the second one is not. Can somebody please offer an assist? My code is below:

$cptQuery = new WP_Query($args = [  
    'post_type' => 'blogs',
    'post_status' => 'publish',
    'posts_per_page' => 24,
    'meta_query' => array(
        array(
            'key' => 'featured_post',
            'value' => 'yes',
            'compare' => 'LIKE'
        ),
    ),
    'orderby' => array(
        'featured_post' => 'DESC',
        'meta_query' => array(
            array(
                'key' => 'featured_post',
                'value' => 'no',
                'compare' => 'LIKE'
            ),
        ),
        'CPT_Images_published-date' => 'DESC',
    ),
    'meta_key' => 'CPT_Images_published-date',
]);

And here is the loop:

while ( $cptQuery->have_posts() ) : $cptQuery->the_post(); 
        setup_postdata( $cptQuery );
        include( get_stylesheet_directory() . '/template-parts/vars-cpt-blogs.php');

        ?>
        <?php if($featuredPost == "yes"): ?>
        <div class="col-4 col-md-4 col-sm-4 featured">
        <?php else: ?>
        <div class="spacer"></div>
        <div class="col-3 col-md-3 col-sm-3 notFeatured">
        <?php endif; ?>
            <div class="card h-100">
                <?php if($heroThumbUrl):?>
                <span class="cardImgWrap" role="img" aria-label="<?php echo $heroThumbDesc; ?>">
                    <img class="card-img-top" src="<?php echo $heroThumbUrl; ?>" alt="<?php echo $heroThumbAlt; ?>" title="<?php echo $heroThumbTitle; ?>" />
                </span>
                <?php else: ?>
                <span class="cardImgWrap" role="img" aria-label="<?php echo $heroImgDesc; ?>">
                    <img class="card-img-top" src="<?php echo $heroImgUrl; ?>" alt="<?php echo $heroImgAlt; ?>" title="<?php echo $heroImgTitle; ?>" />
                </span>
                <?php endif;?>
                <div class="card-body">
                    <?php if ($h1Title): ?>
                    <h5 class="card-title"><?php echo $h1Title; ?></h5>
                    <?php endif; ?>
                    <?php if ($blogExcerpt): ?>
                    <p class="card-text"><?php echo $blogExcerpt; ?></s>
                    <?php endif; ?>
                </div>
                <a class="ctaButton clickTrackCTAButton blogs" href="<?php the_permalink();?>" title='Read "<?php echo $h1Title; ?>" Now'><i class="fa-solid fa-blog"></i> Read This Blog</a>
            </div>
        </div>
    <?php endwhile; ?>
<?php wp_reset_postdata();
} else { ?>
<?php echo esc_html__( 'No posts matching the query were found.', 'your-translate-domain' ); ?>

I should see four (4) posts, 2 "featured" 2 "not featured" and I'm only seeing two (2) featured.

enter image description here

Please help. Thanks!

1 Answer 1

0

You can use the relation = OR in your meta_query args. Something like this:

$args = [  
    'post_type' => 'blogs',
    'post_status' => 'publish',
    'posts_per_page' => 24,
    'meta_query' => array(
        'relation' => 'OR',
        'featured_clause' => array(
            'key' => 'featured_post',
            'value' => 'yes',
            'compare' => '='
        ),
        'not_featured_clause' => array(
            'key' => 'featured_post',
            'value' => 'no',
            'compare' => '='
        )
    ),
    'orderby' => array(
        'featured_clause' => 'DESC',
        'CPT_Images_published-date' => 'DESC'
    ),
    'meta_key' => 'CPT_Images_published-date',
];

$cptQuery = new WP_Query($args);

Note: The code above is just an example. It's not 100% gonna work with the rest of your code, so try adjusting it according to your needs.

But if you're going to limit the featured_post = yes to just 3 posts, WP_Query doesn't directly provide a mechanism to limit results based on meta values. But a way around this is running two separate queries. Something like this:

Query for Featured Posts (max 3)

$featured_args = [
    'post_type' => 'blogs',
    'post_status' => 'publish',
    'posts_per_page' => 3, // Limit to 3 posts
    'meta_query' => [
        [
            'key' => 'featured_post',
            'value' => 'yes',
            'compare' => '='
        ]
    ],
    'orderby' => 'CPT_Images_published-date',
    'order' => 'DESC',
    'meta_key' => 'CPT_Images_published-date'
];

$featured_posts = new WP_Query($featured_args);

Query for Non-Featured Posts

$non_featured_args = [
    'post_type' => 'blogs',
    'post_status' => 'publish',
    'posts_per_page' => 21, // Adjusting for 3 featured posts to maintain total 24
    'meta_query' => [
        [
            'key' => 'featured_post',
            'value' => 'no',
            'compare' => '='
        ]
    ],
    'orderby' => 'CPT_Images_published-date',
    'order' => 'DESC',
    'meta_key' => 'CPT_Images_published-date'
];

$non_featured_posts = new WP_Query($non_featured_args);

Then merge the results in your loop like this:

$all_posts = array_merge($featured_posts->posts, $non_featured_posts->posts);

foreach ($all_posts as $post) {
    setup_postdata($post);
    // your loop content here
}

wp_reset_postdata();

Note: Again the code is just an example for you to use as refference. Please test it out, and adjust to make it work with your current code.

By doing that, you get a maximum of 3 featured posts, then fill up the rest with non-featured posts. This ensures that your front end displays up to 24 posts with the desired prioritization.

I hope this helps!

1
  • Thank you Ray. This was a HUGE help. The separate queries for restricting the featured posts and using the array_merge() didn't work. They only returned a single post and repeated it, almost as if the wp_reset_postdata function was not there. But it was. right after the close of the foreach. I even moved it inside the foreach to test it. Had the same error. But your first query with the 2 separate arrays using the "OR" relation worked brilliantly. So, for now, I can roll with that until I figure out how to mod the separate arrays and get them to work. Thanks again for your help.
    – Mitch S
    Commented Sep 21, 2023 at 1:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.