Skip to content

Instantly share code, notes, and snippets.

@gunderwonder
Created November 6, 2011 17:28
Show Gist options
  • Save gunderwonder/1343203 to your computer and use it in GitHub Desktop.
Save gunderwonder/1343203 to your computer and use it in GitHub Desktop.
WordPress post iterator
<?php
/* Iterator for arrays of WordPress posts or `WP_Query`.
*
* Simplifies "the loop" by automatically handling the `$post` global for each iteration
* (calling `the_post()`, `setup_postdata()` etc.) and makes sure to reset the global state when the loop has finished.
*
* Usage:
* Loop over ten last posts:
* <?php foreach (new WPQueryIterator(array('post_type' => 'post', 'posts_per_page' => 10)) as $i => $p): ?>
* <?php the_title(); ?>
* <?php the_excerpt(); ?>
* <?php the_content(); // etc. ?>
* <?php endforeach; ?>
*
* Iterator objects are proxies for WP_Query methods and properties:
* <?php $q = new WPQueryIterator(); ?>
* <?php $post_count = $q->found_posts; ?>
*
* Use `WPPostIterator` for arrays of posts (returned from SQL queries).
*
* Compare to the "classic" way:
* <?php $q = new WP_Query(array('post_type' => 'post', 'posts_per_page' => 10)) ?>
* <?php $i = 0; ?>
* <?php while($q->have_posts()): ?>
* <?php $q->the_post() ?>
* <?php the_title(); ?>
* <?php the_excerpt(); ?>
* <?php the_content(); // etc. ?>
* <?php $i++; ?>
* <?php endwhile; ?>
* <?php wp_reset_postdata() ?>
*/
class WPPostIterator implements Iterator {
protected $index = 0;
public function __construct($posts) {
global $post;
$this->original_post = $post;
$this->posts = $posts;
}
function rewind() {
$this->index = 0;
$this->current();
}
function current() {
if (!isset($this->posts[$this->key()]))
return NULL;
$current_post = $this->posts[$this->index];
$GLOBALS['post'] = $current_post;
setup_postdata($current_post);
return $current_post;
}
function key() {
return $this->index;
}
function next() {
$this->index++;
$valid = isset($this->posts[$this->key()]);
}
function valid() {
$valid = isset($this->posts[$this->key()]);
if (!$valid) {
wp_reset_query();
wp_reset_postdata();
setup_postdata($this->original_post);
$GLOBALS['post'] = $this->original_post;
}
return $valid;
}
}
class WPQueryIterator extends WPPostIterator {
protected $query = NULL;
public function __construct($query_arguments = array()) {
global $post;
$this->query = new WP_Query($query_arguments);
parent::__construct($this->query->posts);
}
// act as proxy for WP_Query
public function __call($method, $arguments) {
if (method_exists($this->query, $method))
return call_user_func_array(array($this->query, $method), $arguments);
}
public function __get($property) {
if (isset($this->query->$property))
return $this->query->$property;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment