When loading/rendering a page, as you are probably aware, WordPress tries to identify which page is being requested by parsing the query string and matching against a list of regex patterns. For example the query string /page/2/
will be matched against a page #2 of the front page, given that page_on_front
is set to false
(that is the "single page or posts list" setting) and there is a sufficient number of posts that a second page is needed. If there isn't, WordPress will instead redirect to the 404 page and return a HTTP 404 status code.
All this happens in WP_Query::parse_query()
. Look specifically at line 1670 where the query object is marked 404 if there was an error running the query.
My guess is in your case the initial query automatically run by WordPress does not match the query you are running yourself, i.e. WordPress is looking for posts with an offset of page 2 while you intend to load posts matching your custom search query.
I would say your best options of circumventing this is 1. making sure your custom query runs first no matter what or 2. preventing WordPress from returning 404 in this particular case.
1. Making sure your custom query runs first
This could be done by adding the following (untested) piece of code in a plugin or your themes functions.php
:
function my_default_query() {
// Conditions required for running your custom query
if (is_home() || is && isset($_GET['s'])) {
query_posts(array(
// your custom query arguments here
));
}
}
add_action('init', 'my_default_query');
2. preventing WordPress from returning 404
This is probably possible to achieve by using a filter on some of values computed in WP_Query::parse_query()
but they're unfortunately not very easy to find and might be "hidden" behind function calls made inside parse_query()
. If that's to much work or not possible you could probably just change the value of $is_404
on the global WP_Query
object.
function my_override_404() {
// Conditions required for overriding 404
if (is_home() || is && isset($_GET['s'])) {
global $wp_query;
$wp_query->is_404 = false;
}
}
add_action('init', 'my_override_404');
And, as Tom J Nowell wrote, index.php
is probably not the appropriate template to use in this case, and will probably fix your issue alone. Posting this answer anyway since it might help in you/others similar situations.
pre_get_posts
to do any main query manipulation. – Milo Jan 28 '13 at 16:05