4

I have 3 different custom post types: 1.) "events", 2.) "winners" and 3.) "offers". How would I go about retrieving the first (latest) post in each of these post types on a single web page (i.e a home page).

Would I use get_posts() or would I have to manipulate the_loop()?

2 Answers 2

3

Yes, get_posts is the safest way to use multiple loops. It does not mess up with the original query.

Another way would be to create new WP_Query objects:

$my_query = new WP_Query($args);
while ($my_query->have_posts()) : $my_query->the_post();

Note: Why you should not use query_posts()

3
  • So should i use get_posts() or WP_Query()? What way would you recommend?
    – dotty
    Oct 6, 2010 at 8:11
  • get_posts() uses WP_Query(), so I personally prefer the later. I find it more powerful, more flexible,...
    – sorich87
    Oct 6, 2010 at 9:19
  • get_posts() worked a treat in conjunction with setup_postdata()
    – dotty
    Oct 6, 2010 at 10:31
1

Hi @dotty:

The answer from @sorich87 is correct, but I thought I'd elaborate a bit. I've coded a class for you called (verbosely) LatestPostPerPostTypeQuery and you can use it in the loop in place of WP_Query, like so:

<ul>
<?php $args = array('post_type'=>'events,winners,offers'); ?>
<?php $query = new LatestPostPerPostTypeQuery($args); ?>
<?php while($query->have_posts()): $query->the_post(); ?>
  <li><?php the_title(); ?></li>
<?php endwhile; ?>
</ul>

Below is the code for the LatestPostPerPostTypeQuery class which you can copy into your theme's functions.php file (or use the code in a plugin if you like.) The nice thing about this alternative to WP_Query is it does a single query to the database instead of one for each of the three post types like you'd be forced to use when using WP_Query() directly.

<?php
class LatestPostPerPostTypeQuery extends WP_Query {
  var $flag;
  function __construct($args=array()) {
    $this->LatestPostPerPostTypeQuery($args);
  }
  function LatestPostPerPostTypeQuery($args=array()) {
    if (isset($args['post_type']) && !is_array($args['post_type']))
      $args['post_type'] = explode(',',$args['post_type']);
    $this->flag = true;
    parent::query($args);
  }
  static function on_load() {
    add_filter('posts_join',array(__CLASS__,'posts_join'),10,2);
  }
  static function posts_join($join,$query) {
    if (isset($query->flag)) {
      global $wpdb;
      $join .=<<<SQL
INNER JOIN (
SELECT post_type,MAX(post_date) AS post_date
FROM {$wpdb->posts}
GROUP BY post_type) max_date ON 
  max_date.post_type={$wpdb->posts}.post_type AND 
  max_date.post_date={$wpdb->posts}.post_date
SQL;
    }
    return $join;
  }
}
LatestPostPerPostTypeQuery::on_load();

I've also posted a standalone file on Gist allowing you grab the source code and drop the example into a file in the root of your website to call it directly from the browser to watch it in action:

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.