0

problem image

Why is this url pattern taking me to a 404 page where i saw in some other sites this same pattern works fine with search and paginate please help me i am new to wordpress and don't know why this is happening anyone who is experienced can tell me whats wrong here looking for helpful answers , thanks in advance

$search = get_query_var("s");
$page_num = get_page_num();

$query = new WP_Query(array(
    "posts_per_page" => 4,
    "paged" => $page_num,
    "post_type" => "post",
    "s"     => $search
));   

get_page_num in functions.php:

function get_page_num(){
    $name = is_front_page() ? "page":"paged";
    $page = get_query_var($name);
    $page = esc_html($page);
    $page = $page ? $page:1;
    return $page;
}
7
  • can you include the code for your search page in the question? Are you sure that there are actually 2 pages worth of search results?
    – Tom J Nowell
    Nov 6, 2021 at 20:50
  • sorry i thought this would not be needed , i have updated it now , after spending some more time i come to know there is already a default loop there in search.php page and i am using WP_Query for pagination Nov 6, 2021 at 21:12
  • I see, but I don't know why a second query is needed, is this to force the results to 4 per page? If so why use a replacement query rather than modifying the main query? I suspect the cause of your problem is that while your secondary $query has a second page, the main query does not, and it's the main query that matters. pre_get_posts would have avoided this problem while being faster
    – Tom J Nowell
    Nov 6, 2021 at 21:14
  • so its basically happing for default loop so is there any way i can make WP_Query to as default ? Nov 6, 2021 at 21:18
  • that's the wrong approach, it was always the wrong approach and the source of your problem. My previous answer already contains the solution, eliminate the new query and modify the original query with pre_get_posts, you don't need a new query to change how many results per page a search query has
    – Tom J Nowell
    Nov 6, 2021 at 22:19

1 Answer 1

2

The reason your search query fails is because you threw away the main query and created a brand new secondary query. Your secondary query has a second page, the main query does not. The main query is what is important, and because it has no second page, a 404 is shown, which is correct behaviour.

Instead of ignoring the main query, modify it. If you want the main query to only show 4 results per page in a search, make it only show 4 results per page when searching. Don't discard it and use new WP_Query with posts_per_page set to 4. Use the pre_get_posts filter to change posts_per_page to 4 in the main query.

A trivial filter in the functions file would have given you what you wanted all along:

add_action( function( \WP_Query $query ) {
    if ( $query->is_search() && $query->is_main_query() ) {
        $query->set( 'posts_per_page', 4 );
    }
} );

With that, a standard post loop and standard pagination work out the box with no custom queries necessary. This is both faster and simpler than new WP_Query

is there any way i can make WP_Query to as default ?

Yes but:

  • it's extreme bad practice
  • it will not fix your problem as anything in the template is too late
  • it will introduce new problems
  • you would still have double the number of queries needed
  • the main query is already a WP_Query, the problem is that you created a new one, this is bad practice.

If you want to modify the main query, modify it via pre_get_posts, don't create a new one.

I strongly recommend reading the pre_get_posts documentation, it will save you a lot of time and make things clearer:

https://developer.wordpress.org/reference/hooks/pre_get_posts/

3
  • thanks for describing things very well which would otherwise took good amount of time to research by myself and now i am very clear about the problem happening under the hood my final question is can i stop redirection to 404 and manage it manually or its a fixed behaviour in wp ? Nov 6, 2021 at 22:45
  • there is no redirect occurring, if you use the filter rather than a secondary query then the problem disappears. Query determines the template, not the other way around. WP didn't perform a search because it loaded search.php, it was the other way around. The main query runs before the template is chosen. So by the time your template is loaded it's too late. The results of the query determine the template, so if no posts are found then the 404.php template is used to show that. Your mental model of how templates work is upside down
    – Tom J Nowell
    Nov 6, 2021 at 23:54
  • If it helps, do not think of the template files in a theme as pages. WordPress takes the URL, turns it into WP_Query parameters using the rewrite rule system, runs that query, then uses the result to decide which template file it needs to display them. E.g. if ->is_search() is true it'll load search.php then exit, or if ->is_singular() is true it loads single.php, etc. All the querying and figuring out which posts etc happens before the template is chosen/loaded. That's why you see people new to WP ask things like "How do I make it use search.php?" which doesn't make sense as a Q.
    – Tom J Nowell
    Nov 7, 2021 at 0:04

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.