0

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:

<?php
    if (isset($_POST["s"])) {
        $search_term = $_POST["s"];
    }

    if (isset($_POST["type"])) {
        switch ($_POST["type"]) {
            case "profile" :
                $post_type = "species";
                break;
            case "glossary" :
                $post_type = "glossary";
                break;
            default :
                $post_type = array( 'post', 'species' );
                break;
        }
    } 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(); ?>">
            <?php
                if (get_post_type() == "species") {
                    get_template_part('list', 'species');
                } else {
                    get_template_part('list', 'index');
                }
            ?>
        </div>
    <?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,

13
  • 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..)..
    – t31os
    Commented Feb 21, 2012 at 15:00
  • 1
    Have you read about the paged and page for paginated results in the related Qs?
    – kaiser
    Commented Feb 21, 2012 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
    – turbonerd
    Commented Feb 21, 2012 at 15:02
  • If it replaces the default search, you may need to use $_REQUEST rather than $_POST Commented Feb 21, 2012 at 15:14
  • OK Stephen, may I enquire why?
    – turbonerd
    Commented Feb 21, 2012 at 15:16

3 Answers 3

2
+100

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:

example.com/?type=species&s=giraffe

You can do:

example.com/species/?s=giraffe

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>
    </select>

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

8
  • 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?
    – turbonerd
    Commented Mar 1, 2012 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
    Commented Mar 1, 2012 at 17:33
  • Here you go: pastebin.com/wXpW3VaE
    – turbonerd
    Commented Mar 1, 2012 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
    Commented Mar 2, 2012 at 10:07
  • Yeah, /species/ definitely works for listing the species!
    – turbonerd
    Commented Mar 2, 2012 at 22:20
3

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.

7
  • 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?
    – turbonerd
    Commented Feb 23, 2012 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). Commented Feb 23, 2012 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.
    – turbonerd
    Commented Feb 23, 2012 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 :-)). Commented Feb 23, 2012 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?
    – turbonerd
    Commented Feb 23, 2012 at 18:02
-1

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 and acknowledge you have read our privacy policy.

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