query_posts breaks pagination

query_posts breaks pagination

Everyone once in a while I’ll find myself amidst some sort of code riddle. More often then not it’s due to a plugin conflict, a CSS selector gone rogue or in most cases some typo where I’m missing a closing bracket, parenthesis or something like that. Although sometimes totally maddening, it’s generally pretty easy to trouble shoot and for the most part I at least know what’s up, just a matter of sifting through everything. I recently had a project where I was working with someone elses code and a theme that was new to me. This particular theme had a pagination that looked like this:

…wich is really pretty common. It’s implemented with the following snippet of php code at the bottom of page.
[php]<?php if (function_exists("emm_paginate")) {
emm_paginate();
} ?>[/php]
Also pretty common.
Here is the paginate function code from the themes functions.php file including all commenting:

[php]
/*******************************
PAGINATION
********************************
* Retrieve or display pagination code.
*
* The defaults for overwriting are:
* ‘page’ – Default is null (int). The current page. This function will
* automatically determine the value.
* ‘pages’ – Default is null (int). The total number of pages. This function will
* automatically determine the value.
* ‘range’ – Default is 3 (int). The number of page links to show before and after
* the current page.
* ‘gap’ – Default is 3 (int). The minimum number of pages before a gap is
* replaced with ellipses (…).
* ‘anchor’ – Default is 1 (int). The number of links to always show at begining
* and end of pagination
* ‘before’ – Default is ‘<div class="emm-paginate">’ (string). The html or text
* to add before the pagination links.
* ‘after’ – Default is ‘</div>’ (string). The html or text to add after the
* pagination links.
* ‘title’ – Default is ‘__(‘Pages:’)’ (string). The text to display before the
* pagination links.
* ‘next_page’ – Default is ‘__(‘&raquo;’)’ (string). The text to use for the
* next page link.
* ‘previous_page’ – Default is ‘__(‘&laquo’)’ (string). The text to use for the
* previous page link.
* ‘echo’ – Default is 1 (int). To return the code instead of echo’ing, set this
* to 0 (zero).
*
*
* @param array|string $args Optional. Override default arguments.
* @return string HTML content, if not displaying.
*/
function emm_paginate($args = null) {
$defaults = array(
‘page’ => null, ‘pages’ => null,
‘range’ => 3, ‘gap’ => 3, ‘anchor’ => 1,
‘before’ => ‘<div class="emm-paginate">’, ‘after’ => ‘</div>’,
‘title’ => __(‘Pages:’),
‘nextpage’ => __(‘&raquo;’), ‘previouspage’ => __(‘&laquo’),
‘echo’ => 1
);
$r = wp_parse_args($args, $defaults);
extract($r, EXTR_SKIP);
if (!$page && !$pages) {
global $wp_query;
$page = get_query_var(‘paged’);
$page = !empty($page) ? intval($page) : 1;
$posts_per_page = intval(get_query_var(‘posts_per_page’));
$pages = intval(ceil($wp_query->found_posts / $posts_per_page));
}
$output = "";
if ($pages > 1) {
$output .= "$before<span class=’emm-title’>$title</span>";
$ellipsis = "<span class=’emm-gap’>…</span>";
if ($page > 1 && !empty($previouspage)) {
$output .= "<a href=’" . get_pagenum_link($page – 1) . "’ class=’emm-prev’>$previouspage</a>";
}
$min_links = $range * 2 + 1;
$block_min = min($page – $range, $pages – $min_links);
$block_high = max($page + $range, $min_links);
$left_gap = (($block_min – $anchor – $gap) > 0) ? true : false;
$right_gap = (($block_high + $anchor + $gap) < $pages) ? true : false;
if ($left_gap && !$right_gap) {
$output .= sprintf(‘%s%s%s’,
emm_paginate_loop(1, $anchor),
$ellipsis,
emm_paginate_loop($block_min, $pages, $page)
);
}
else if ($left_gap && $right_gap) {
$output .= sprintf(‘%s%s%s%s%s’,
emm_paginate_loop(1, $anchor),
$ellipsis,
emm_paginate_loop($block_min, $block_high, $page),
$ellipsis,
emm_paginate_loop(($pages – $anchor + 1), $pages)
);
}
else if ($right_gap && !$left_gap) {
$output .= sprintf(‘%s%s%s’,
emm_paginate_loop(1, $block_high, $page),
$ellipsis,
emm_paginate_loop(($pages – $anchor + 1), $pages)
);
}
else {
$output .= emm_paginate_loop(1, $pages, $page);
}
if ($page < $pages && !empty($nextpage)) {
$output .= "<a href=’" . get_pagenum_link($page + 1) . "’ class=’emm-next’>$nextpage</a>";
}
$output .= $after;
}
if ($echo) {
echo $output;
}
return $output;
}
/**
* Helper function for pagination which builds the page links.
*
* @access private
*
* @author Eric Martin <eric@ericmmartin.com>
* @copyright Copyright (c) 2009, Eric Martin
* @version 1.0
*
* @param int $start The first link page.
* @param int $max The last link page.
* @return int $page Optional, default is 0. The current page.
*/
function emm_paginate_loop($start, $max, $page = 0) {
$output = "";
for ($i = $start; $i <= $max; $i++) {
$output .= ($page === intval($i))
? "<span class=’emm-page emm-current’>$i</span>"
: "<a href=’" . get_pagenum_link($i) . "’ class=’emm-page’>$i</a>";
}
return $output;
}
[/php]
This worked fine. To back up just a bit for a minute. On this same project, I was asked to create a number of interactive aspects. Most notably, a page where the user could post to a separate page via the front end. The main purpose of this was for users to add image & videos. I’ve done things like this before with WP. Just made a new page template pretty much identical to the blog page but with the addition of this post query:
[php]<?php query_posts(‘cat=22’); ?>
//loop here[/php]
I had it set up like so… When a user posts and entry, said entry is is automatically given a specif category. In this case the categories ID was 22 as you may have already noticed. If your at all familiar with PHP pr WordPress post querys then you know this isn’t exactly ground breaking territory.
At first, it appear that everything was working the way I wanted. Posts were, showing up, media uploads where displaying accordingly so I retired for the day. I returned the following day and decided to post a few more times from few different test accounts to assure functionality. After a few additional posts, WordPress had kindly generated a second page thanks to the pagination function I have posted above. Here is where things went haywire. The second page I wa expecting to see was anything but. Broken images, repeat posts etc. I thought for sure it was something the front-end posting I had implemented but quite frankly I was quite bewildered. I disabled all of my plugins to assure I wasn’t going crazy and the problem persisted. Then it hit me. I commented out:
[php]<?php if (function_exists("emm_paginate")) {
emm_paginate();
} ?>[/php]
…And everything was back to normal. At this point I at least knew the root of the problem. Thanks to a colleague of mine who informed me “When you place a call to query_posts() in one of your Template files before The Loop begins. The wp_query object will generate a new SQL query using your parameters. When you do this, WordPress ignores the other parameters it receives via the URL (such as page number or category).”
Fair enough. The solution:
[php]<?php query_posts(‘cat=22&paged=’.$paged); ?>
//loop here[/php]
And just to be on the safe side…
[php][/php]<?php wp_reset_query(); ?>[php][/php]
…at the end of the loop. Quite honestly, I’m not sure you need it, but I wanted to be sure.