One of the most boring, cumbersome and dangerous things with WordPress is getting and working with posts in custom loops.

A common situation is like this:

<?php // Setup a wp_query object that gets the pages with id 1,2 and 3 $query = new wp_query('post_type=page&post__in=1,2,3'); while ($query->have_posts() ) : $query->the_post(); echo "<p>Found a post with title: " . get_the_title() . "</p>"; endwhile; wp_reset_postdata(); ?>

That’s a bit cumbersome I think. Do I really need to do that while-thingie, that the_post()-method-thingie and that wp_reset_postdata()-thingie each time? It feels a bit… repetitive. And dangerous, since if I forget to reset the postdata I can screw up other loops and functions and plugins and my site (that often is a client site..) is starting to fall apart, loop by loop.

with_posts(): a fancy solution with a callback

So, I give you my solution to this problem: the with_posts()-function. Let’s do the same thing again, using my approach:

<?php // Get the pages 1,2 and 3 and do some things with them with_posts("1,2,3'", function() { echo "<p>Found a post with title: " . get_the_title() . "</p>"; }); ?>

Using with_posts() I went from 6 lines to 3 lines.

Maybe it’s just 3 lines less you think, but hey it’s 3 lines less every time you want to loop something! That, plus you won’t forget that reset_postdata or setup_postdata thing again.

The magic is in the callback function: inside it you will automagically get the current post as the current post and it’s called once for each post in the matching query. You can use all the common stuff like the_title, the_permalink, edit_post_link, the_content, and so on.

Oh! And you can pass other stuff into the with_post-function too (ids, slugs, query strings…), to get any mix of posts. This example uses a regular wp_query as the base, to get some posts from a custom post type:

<?php // Loop through a wp query obj $wp_query_obj = new wp_query('post_type=regions&posts_per_page=3&orderby=title&order=asc'); with_posts($wp_query_obj, function($post, $arr_info) { echo "<p>I am post number" . $arr_info["current_post"] . " of " . $arr_info["post_count"] " found post(s).</p>"; echo "<p>My title is: " . get_the_title() . "</p>"; echo "<p>And my slug is: " . $post->post_name . "</p>"; }); ?>

The function is posted in a Gist on Github for your viewing and forking pleasure, and I’ve also created a Gist with all kinds of examples, so check it out and you’ll probably hopefully get the hang of it.

What can i say – I love this little function, and I hope you do.

Now, feedback me!