1

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>';
} 
?>
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>';
}
  • 1
    Thank you!! This looks very smart. Didnt cross my mind to use wpcron for this. – human1fy Oct 27 '18 at 10:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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