wp query - Display tags with random thumbnail from selection of posts with that tag

admin2025-06-07  14

What I want to achieve consists of two parts:

First a set of containers that display each tag (with name, description and link). This is easily achieved with a get_tags and foreach loop.

<?php
$tags = get_tags( $args );

foreach ( $tags as $tag ) {
    // get tag link
    $tag_link = get_tag_link( $tag->term_id );
    // display content
    echo '<div id="tag-block">'
       . $tag->name
       . $tag->description
       . '<a href="'.$tag_link.'">see tag archive</a>'
       . '</div>';
} 
?>

Now the hard part:

I want to show ( query ) an image in each tag-container to illustrate the tag, with the following conditions ( arguments ):

for each tag:

  • a selection of images ( post_thumbnail ) is pulled from all the posts for the current tag.

  • order=>'rand', so each refresh will show different picture.

  • only one is shown ( posts_per_page=1 )

The only way I can think of, is to grab all tags, put them in a foreach loop, and within each instance run a separate wp_query with those arguments.

However, with 7-8 tags this code will be running too many queries on one page. As far as I know, (and tested) this is terribly inefficient performance-wise.

TLDR: The following code works but running all these separate queries is bad performance. I could use a hand here.

<?php
$tags = get_tags( $args );

foreach ( $tags as $tag ) {
    // get tag link
    $tag_link = get_tag_link( $tag->term_id );

    // get random image for this tag
    $args = array(
    'post_type' => 'custom_event',
    'order' => 'rand',
    'tag__in' => array ($tag->term_id),
    'posts_per_page' => 1,
    );

    $query = new WP_query ( $args );

    // hmmm this is probably bad
    while ( $query->have_posts() ) { $query->the_post();

      the_post_thumbnail( $post->id );

    } wp_reset_postdata();

    // display rest of content
    echo '<div id="tag-block">'
       . $tag->name
       . $tag->description
       . '<a href="'.$tag_link.'">see tag archive</a>'
       . '</div>';
} 
?>

What I want to achieve consists of two parts:

First a set of containers that display each tag (with name, description and link). This is easily achieved with a get_tags and foreach loop.

<?php
$tags = get_tags( $args );

foreach ( $tags as $tag ) {
    // get tag link
    $tag_link = get_tag_link( $tag->term_id );
    // display content
    echo '<div id="tag-block">'
       . $tag->name
       . $tag->description
       . '<a href="'.$tag_link.'">see tag archive</a>'
       . '</div>';
} 
?>

Now the hard part:

I want to show ( query ) an image in each tag-container to illustrate the tag, with the following conditions ( arguments ):

for each tag:

  • a selection of images ( post_thumbnail ) is pulled from all the posts for the current tag.

  • order=>'rand', so each refresh will show different picture.

  • only one is shown ( posts_per_page=1 )

The only way I can think of, is to grab all tags, put them in a foreach loop, and within each instance run a separate wp_query with those arguments.

However, with 7-8 tags this code will be running too many queries on one page. As far as I know, (and tested) this is terribly inefficient performance-wise.

TLDR: The following code works but running all these separate queries is bad performance. I could use a hand here.

<?php
$tags = get_tags( $args );

foreach ( $tags as $tag ) {
    // get tag link
    $tag_link = get_tag_link( $tag->term_id );

    // get random image for this tag
    $args = array(
    'post_type' => 'custom_event',
    'order' => 'rand',
    'tag__in' => array ($tag->term_id),
    'posts_per_page' => 1,
    );

    $query = new WP_query ( $args );

    // hmmm this is probably bad
    while ( $query->have_posts() ) { $query->the_post();

      the_post_thumbnail( $post->id );

    } wp_reset_postdata();

    // display rest of content
    echo '<div id="tag-block">'
       . $tag->name
       . $tag->description
       . '<a href="'.$tag_link.'">see tag archive</a>'
       . '</div>';
} 
?>
Share Improve this question edited Oct 26, 2018 at 18:41 human1fy asked Oct 26, 2018 at 16:33 human1fyhuman1fy 134 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

I am thinking about leveraging the wp_cron and transients.

You can create a helper function which will do the heavy lifting and do all the queries you need, but schedule it to be done like every 12 hours - twice daily (or more, depending on the frequency of new posts) using wp_cron API.

Basically, this is what you need:

Helper function and WP cron job

/**
 * Helper function to update tag transients with post IDs
 */
function wpse317707_update_tag_transients() {
    $tags = get_tags(); // add args

    /** @var WP_Term $tag */
    foreach ( $tags as $tag ) {

        // get random image for this tag
        $args = array(
            'post_type' => 'custom_event',
            'tag__in' => array ( $tag->term_id ),
            'posts_per_page' => -1,
        );

        $query = new WP_query ( $args );
        $post_ids = wp_list_pluck( $query->posts, 'ID' );

        set_transient( $tag->slug . '-tag-posts', $post_ids, DAY_IN_SECONDS );
    }
}

add_action( 'update_tag_transients', 'wpse317707_update_tag_transients' );

/**
 * Schedule WP Cron job
 */
if ( ! wp_next_scheduled( 'update_tag_transients' ) ) {
    wp_schedule_event( time(), 'twicedaily', 'update_tag_transients' );
}

Your code, adjusted

$tags = get_tags( $args );

foreach ( $tags as $tag ) {
    // get tag link
    $tag_link = get_tag_link( $tag->term_id );

    // get post IDs
    $post_ids = get_transient( $tag->slug . '-tag-posts' );

    // get random ID
    $random_id = $post_ids[ array_rand( $post_ids, 1 ) ];

    the_post_thumbnail( $random_id );

    // display content
    echo '<div id="tag-block">'
         . $tag->name
         . $tag->description
         . '<a href="'.$tag_link.'">see tag archive</a>'
         . '</div>';
}
转载请注明原文地址:http://conceptsofalgorithm.com/Algorithm/1749229519a317448.html

最新回复(0)