I have a few different searches on my website:

  • "Species profiles" (custom post type search)
  • "Glossary" (custom post type search)
  • Generic, site-wide search

Currently I'm using search.php; $_POST["type"] to determine which search has been used and and $_POST["s"] for the query term:

    if (isset($_POST["s"])) {
        $search_term = $_POST["s"];

    if (isset($_POST["type"])) {
        switch ($_POST["type"]) {
            case "profile" :
                $post_type = "species";
            case "glossary" :
                $post_type = "glossary";
            default :
                $post_type = array( 'post', 'species' );
    } else {
        $post_type = array( 'post', 'species' );

    $args = array(
        's' => $search_term,
        'post_type' => $post_type

<?php get_template_part('searchresults'); ?>

This works well enough, however when I then try to use next_posts_link or previous_posts_link, it doesn't work. The URL changes to mywebsite.com/page/2/ and displays a Sorry, you're looking for something that isn't here message as per standard 404 on my site.

EDIT I've now updated my code so that it includes $paged as follows (I've also tried changing get_query_var to 'paged' rather than 'page' but it makes no difference):

    $paged = (get_query_var('page')) ? get_query_var('page') : 1;

    $args = array(
        's' => $search_term,
        'post_type' => $post_type,
        'paged' => $paged

However, the same problem is occurring.

Here is the code from searchresults.php for @MarkDuncan

<?php global $args; ?>

<?php $query = new WP_Query ( $args ); ?>

<?php if ($query->have_posts()) : ?>

    <?php if ($s) : ?>
        <p class="info">Search results for <em>&#8216;<?php echo $s ?>&#8217;</em></p>
    <?php else : ?>
        <p class="info">Search results:</p>
    <?php endif; ?>

    <?php while ( $query->have_posts() ) : $query->the_post(); ?>
        <div class="post" id="post-<?php the_ID(); ?>">
                if (get_post_type() == "species") {
                    get_template_part('list', 'species');
                } else {
                    get_template_part('list', 'index');
    <?php endwhile; ?>

    <div class="navigation"><?php next_posts_link('&laquo; Previous Entries') ?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<?php previous_posts_link('Next Entries &raquo;') ?></div>

<?php else : ?>

    <?php get_template_part( 'notfound' ); ?>

<?php endif; ?>

Is there a way of resolving this issue?

Thanks in advance,

  • What happens inside the searchresults template(can you add the code from that file to the question), are you passing in those args as is? You'll lose any other query vars intended for the query that way..(such as paging values, etc..).. – Mark Duncan Feb 21 '12 at 15:00
  • 1
    Have you read about the paged and page for paginated results in the related Qs? – kaiser Feb 21 '12 at 15:00
  • Ah, no I hadn't - I didn't think it was relevant. Just found a good post which might help me though: wordpress.stackexchange.com/questions/10459 – dunc Feb 21 '12 at 15:02
  • If it replaces the default search, you may need to use $_REQUEST rather than $_POST – Stephen Harris Feb 21 '12 at 15:14
  • OK Stephen, may I enquire why? – dunc Feb 21 '12 at 15:16

You don't need the type variable and other bits of custom search query code, or custom functions like the other answers.

In your searchbox, instead of submitting the form to / submit it to /my_post_type/ instead! WordPress will handle all the rest for you automagically, with no effort involved.

What's more this means all the usual functions will work just as you expected them to!

For example, instead of:


You can do:


Where example.com/species is your custom post type archive page.

And for your Species specific search box:

<form role="search" method="get" id="searchform" action="<?php echo home_url( '/species/' ); ?>">

If you'd like a single searchbox with a choice, you can change the home_url function parameter from '/species/' to '/', then add a dropdown box field whose name is 'post_type' containing the different values you desire e.g.:

<form role="search" method="get" id="searchform" action="<?php echo home_url( '/species/' ); ?>">
    <select name="post_type">
      <option value="">Sitewide</option>
      <option value="species">Species</option>
      <option value="Glossary">Glossary</option>

Doing it this way means no custom queries, and no faffing around with variables. All the functionality is provided out of the box by WordPress, and the only extra part you need to do is change your searchbox html!

All the normal wordpress functions on archive pages will now work as expected with no additional steps

You can use the same trick with categories, tags, taxonomies, author and date archives.

So remove the WP_Query in your search templates, and remove the extra code you put above the get_template_part line in search.php, change your search box, and make sure custom permalinks are activated

  • OK Tom, that's great, thanks. I've done most of that now. However, oddly, my <form action="<?php echo home_url( '/glossary/' ); ?>" method="get"> is producing URLs like /glossary/?s=queryterm where <form id="profilesearch" action="<?php echo home_url( '/species/' ); ?>" method="get"> is producing URLs like /search/queryterm. Any idea what I might've done wrong there? – dunc Mar 1 '12 at 14:01
  • hmmm Im not sure, do you have somewhere I can see the markup for myself in its entirety and try it out? It is 'species' and not 'Species' right? and going to /species/ gives you the post archive listing of species posts right? – Tom J Nowell Mar 1 '12 at 17:33
  • Here you go: pastebin.com/wXpW3VaE – dunc Mar 1 '12 at 23:10
  • hmm I can't see anything that would be causing that from what I can see, can you verify going to the URL /species/ actually shows species posts? If not, can I see your code for registering the post types? – Tom J Nowell Mar 2 '12 at 10:07
  • Yeah, /species/ definitely works for listing the species! – dunc Mar 2 '12 at 22:20

Because you are using <?php $query = new WP_Query ( $args ); ?> the wp_query global isn't changed (used by next_posts_link).

So you can change the new WP_Query call to just query_posts( $args ); (and change your loop without the $query->).

Or you can overwrite the <?php global wp_query; $wp_query = new WP_Query ( ); $wp_query->query($args); ?> and change your loop accordingly ($quey-> to $wp->query).

If you want to use the original query after your search, you can store it in a temp variable before you alter it global $wp_query; $temp = $wp_query;. After the loop you can do $wp_query = $temp to set it back to the original query.

  • I read somewhere - though I can't remember details - that I shouldn't be using query_posts, rather WP_Query. Could you explain why your code makes a difference to what I'm trying to do? Also, am I using the correct method of navigating between the pages with next_pages_link? – dunc Feb 23 '12 at 16:35
  • 3
    wordpress.stackexchange.com/questions/1753/… (what a great post of Rarst) In your example you want to completely overwrite the loop, because your search loop is your mainloop, so query_posts it is. The difference with your code is also explained in the answer of Rarst, it has to do with setting up all the global variables (which next_posts_link uses for instance). You probably mean next_posts_link and yes that's one of the functions you could use for pagination (paginate_links is another one). – Rob Vermeer Feb 23 '12 at 16:52
  • That's a fantastic post, but I must say I'm still struggling to understand it entirely. I might just have to dedicate some time to it later this evening and see if I can get my head around it :) Thanks Rob. – dunc Feb 23 '12 at 17:24
  • 1
    Simplify: query_posts, always main loop. wp_query secondary loop, or if you overwrite the $wp_query main loop (the image shows everything :-)). – Rob Vermeer Feb 23 '12 at 17:33
  • I understand the main loop thing - and I guess that's thus what I should be using - but what is a secondary loop? Is that used if another loop (in addition to the standard post loop) is required on the same page? – dunc Feb 23 '12 at 18:02

I would say the fastest way to achieve this kind of link is like that:

function custom_next_comments_link( $label = '', $max_page = 0, $query = array() ) {
    global $wp_query;
    $wp_query = $query;
    echo get_next_comments_link( $label, $max_page );

function custom_previous_comments_link( $label = '', $query = array() ) {
    global $wp_query;
    $wp_query = $query;
    echo get_previous_comments_link( $label );

And them you would pass as the $query argument using your new WP_Query();

Hope I've helped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.