4

I have a custom post type 'quotes' and I would like to display a random entry on the homepage each day.

This is the code I currently have to display the content:

            <?php query_posts( 'post_type=quote&orderby=rand&showposts=1' ); ?>
            <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
            <?php if ( has_post_thumbnail() ) {
                the_post_thumbnail( 'thumbnail-quote' );
                } else { ?>
                <img src="<?php bloginfo('template_directory'); ?>/img/thumb1.jpg" alt="x" class="quote_person" />
                <?php } ?>
        <div class="quote_container">
            <span class="quote_intro hstack">Quote of the day:</span><a class="quote_tweet hstack" href="#">Tweet this quote <i class="fa fa-twitter"></i></a>
            <div class="quote_message white gstack"><?php the_field('quote'); ?></div>
            <div class="quote_source white hstack"><?php the_field('attribution'); ?></div>
        </div>
        <?php endwhile; endif; ?>

EDIT:

Following the helpful suggestions I now have something that looks like the following:

            <?php 

        if ( false === ( $quotes = get_transient( 'random_quote' ) ) ) {
          // It wasn't there, so regenerate the data and save the transient

          $args = array(
             'post_type' => 'quote',
             'orderby'   => 'rand',
             'posts_per_page' => '1'
          );

          $quotes = get_posts( $args );

          //Now we store the array for one day.
          //Just change the last parameter for another timespan in seconds.
          $seconds_until_next_day = strtotime('tomorrow') - time();
          set_transient( 'random_quote', $quotes, $seconds_until_next_day );
        }

        foreach ( $quotes as $post ) : setup_postdata( $post );
        if ( have_posts()) : while (have_posts()) : the_post();

            if ( has_post_thumbnail() ) {
            the_post_thumbnail( 'thumbnail-quote' );
            } else { '<img src="' . bloginfo('template_directory') .'/img/thumb1.jpg" alt="University of Lincoln" class="quote_person" />'
            echo '<div class="quote_container">
                <span class="quote_intro hstack">Quote of the day:</span><a class="quote_tweet hstack" href="#">Tweet this quote <i class="fa fa-twitter"></i></a>
                <div class="quote_message white gstack" id="thequote">' . the_field('quote') . '</div>
                <div class="quote_source white hstack">' . the_field('attribution') . '</div>
            </div>
            '; }

        endforeach; 
        wp_reset_postdata();


        ?>

I'm not quite sure if I've got the foreach statement quite right.

  • Are we talking about each day as in calendar day or just changing in 24h intervals? – kraftner Aug 25 '15 at 10:21
  • @kraftner Either would work. – cubechris Aug 25 '15 at 10:32
10

First of all you really shouldn't be using query_posts(). Read this excellent explanation why.

Then this is a perfect use case for transients.

You just get the post once and then cache it for 24 hours using the Transients API.

if ( false === ( $quotes = get_transient( 'random_quote' ) ) ) {
  // It wasn't there, so regenerate the data and save the transient

  $args = array(
     'post_type' => 'quote',
     'orderby'   => 'rand',
     'posts_per_page' => '1'
  );

  $quotes = get_posts( $args );

  //Now we store the array for one day.
  //Just change the last parameter for another timespan in seconds.
  set_transient( 'random_quote', $quotes, DAY_IN_SECONDS );
}

If your goal was to have it bound to calendar days and not 24 hours from last request replace the last line with the following. (props to chaos)

$seconds_until_next_day = strtotime('tomorrow') - time();
set_transient( 'random_quote', $quotes, $seconds_until_next_day );

After you have got the data you can just display it any way you want:

foreach ( $quotes as $post ) : setup_postdata( $post );

  [...]
  the_title();
  [...]

endforeach; 
wp_reset_postdata();

See this link for more examples.

EDIT:

This should do the trick in your particular situation:

foreach ( $quotes as $post ) : setup_postdata( $post );

    if ( has_post_thumbnail() ) {
                the_post_thumbnail( 'thumbnail-quote' );
    } else { ?>
            <img src="<?php echo get_stylesheet_directory_uri (); ?>/img/thumb1.jpg" alt="x" class="quote_person" />
    <?php } ?>
    <div class="quote_container">
        <span class="quote_intro hstack">Quote of the day:</span><a class="quote_tweet hstack" href="#">Tweet this quote <i class="fa fa-twitter"></i></a>
        <div class="quote_message white gstack"><?php the_field('quote'); ?></div>
        <div class="quote_source white hstack"><?php the_field('attribution'); ?></div>
    </div>

<?php endforeach; 
wp_reset_postdata();
  • 1
    +1 and just a note about the foreach loop: I think it would be better to use $post instead of $quote, if you call the_title(). See for example this comment. – birgire Aug 25 '15 at 10:50
  • 2
    Updated as suggested by @birgire. – kraftner Aug 25 '15 at 10:52
  • Exactly my line of thought. Really really good answer. – Pieter Goosen Aug 25 '15 at 12:03
  • Thanks @kraftner - this looks like it's going to do what I need. I'm just unsure how to work the foreach statement correctly? I think I must be getting the syntax slightly wrong - I've edited my original question. Thanks again for your help. – cubechris Aug 25 '15 at 14:18
  • Updated my answer. – kraftner Aug 25 '15 at 14: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.