Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm at a loss, I've found several unanswered questions related to this one. I have a static post page which has a search form in the sidebar. What I want to happen is to type in a keyword and then 'filter'(return with ajax) only the posts that fit the search. I also want it to be paginated.

I've found several ways to manipulate $wp_query so that I can use the same loop for the ajax call. Unfortunately when I look global $wp_query in functions.php where my callback action is, it is basically null or initialized to default parameters. I debugging everything locally, I wonder if that would affect anything. I haven't confirmed it but shouldn't that global variable stay the same unless something explicitly happens to it(like navigating to a new page)?

This is the callback in functions.php

function cbSearch()
{
    $counter=1;
    $html="";
    global $wp_query;


    if ( have_posts() )
    {
        while ( have_posts() )
        {
            the_post();
            $html.="<div class='news-page-item'>";
            $html.=the_title('<h2>','</h2>');
            $date= strtoupper(get_the_date('F Y'));
            $subtitle = get_post_meta (get_the_ID(), 'subtitle', $single = true);
            $summary = get_the_excerpt();//get_post_meta (get_the_ID(), 'summary', $single = true);
            $html.="<div class='fg-grey f12 mt8'>".$subtitle." - ".$date."</div>";
            $upload_dir = wp_upload_dir();
            $html.="<img class='mv25' src='".$upload_dir['baseurl']."/news-item.jpg' alt='".get_the_title()."' />";
            $html.="<p class='f15'>";
            $html.=$summary;
            $html.="<a href='".get_permalink()."' class='fg-grey f11'>&nbsp;&rsaquo;&nbsp;READ MORE</a>";
            $html.="</p>";
            if ($counter != count($posts))
            {
                $html.="<hr class='mv30 c888' />";
            }
            ++$counter;

            $html.="</div>";
            echo $html;
            $html="";
        }
    }
    $html.="<div id='news-page-nav'>";
    $html.="<span class='left'>";
    $html.=get_previous_posts_link(" P ");
    $html.="</span>";
    $html.="<span class='right'>";
    $html.=get_next_posts_link(" N ");
    $html.="</span></div>";
    echo $html;

    die();
}

I use a breakpoint in this function to find the $wp_query parameters.

This is what is returned when I do a var_dump immediately after calling global $wp_query;

object(WP_Query)[145]
  public 'query' => null
  public 'query_vars' => 
    array
      empty
  public 'tax_query' => null
  public 'meta_query' => boolean false
  public 'queried_object' => null
  public 'queried_object_id' => null
  public 'request' => null
  public 'posts' => null
  public 'post_count' => int 0
  public 'current_post' => int -1
  public 'in_the_loop' => boolean false
  public 'post' => null
  public 'comments' => null
  public 'comment_count' => int 0
  public 'current_comment' => int -1
  public 'comment' => null
  public 'found_posts' => int 0
  public 'max_num_pages' => int 0
  public 'max_num_comment_pages' => int 0
  public 'is_single' => boolean false
  public 'is_preview' => boolean false
  public 'is_page' => boolean false
  public 'is_archive' => boolean false
  public 'is_date' => boolean false
  public 'is_year' => boolean false
  public 'is_month' => boolean false
  public 'is_day' => boolean false
  public 'is_time' => boolean false
  public 'is_author' => boolean false
  public 'is_category' => boolean false
  public 'is_tag' => boolean false
  public 'is_tax' => boolean false
  public 'is_search' => boolean false
  public 'is_feed' => boolean false
  public 'is_comment_feed' => boolean false
  public 'is_trackback' => boolean false
  public 'is_home' => boolean false
  public 'is_404' => boolean false
  public 'is_comments_popup' => boolean false
  public 'is_paged' => boolean false
  public 'is_admin' => boolean false
  public 'is_attachment' => boolean false
  public 'is_singular' => boolean false
  public 'is_robots' => boolean false
  public 'is_posts_page' => boolean false
  public 'is_post_type_archive' => boolean false
  public 'query_vars_hash' => boolean false
  public 'query_vars_changed' => boolean true
  public 'thumbnails_cached' => boolean false

I know that ajax function is working. Can anyone tell me why $wp_query turns into garbage somewhere between page load and the http request?

EDIT:

After considering the logic a little bit more I don't think typical pagination will work with ajax. Since next/previous_posts_link provides a url for a link, that means $wp_query parameters are loaded based on the page template any additional parameters in the url. Only when $wp_query knows it's loading a page template next/previous_posts_link will return http://domain.com/new/page/2/ instead of http://domain.com/wp-admin/admin-ajax.php?paged=2.

I'm considering using get_posts() in the ajax call and returning the posts for one page and creating next/previous links that call the ajax function with an offset representing the page number.

share|improve this question

2 Answers 2

up vote 0 down vote accepted

The original request that loaded the page you are making the AJAX request from ended as soon as the page was sent to your browser. That connection is closed and it is gone from memory.

When you make an AJAX request, it's a new request, so $wp_query is empty because you haven't queried anything. You need to create a new WP_Query instance and query the database, passing whatever query variables you want to set in this query via your AJAX function.

share|improve this answer
    
I was afraid of that. Thats a fair amount of parameters to sift through to match my post page. Do you have any recommendations on how to set these automatically? Also, do you have any insight on the issue of pagination? I will edit the question to include my results for next/previous_posts_link. –  Gecko Jun 7 '12 at 0:58

From Milo's input I successfully created and tested my function to the specifications of the question. An AJAX function that returns posts that match a search query and is paginated. First thing to do is check for any plugins that affect search results. The reason is that I had the 'Search Everything' plugin running. While it was meant to search for more results and highlight the search terms, it will change any instance of new WP_Query(); making it useless.

This is the callback function to load posts with ajax. The calling function works like any other client side request, echoing the results to an empty div.

function cbSearch()
{
    $counter = 1;
    $max = 4;
    $html = "";
    //Variables passed through $_POST
    $s = $_POST['src'];
    //the first time you call this function page number should be 1
    //Additional pages/functions/links are created with this code
    $page_num = $_POST['idx'];

    //Assuming the old $wp_query is basically null, 
    //there's no reason to copy previous parameters, just make a new one
    $search_query = array('s' => $s, 'posts_per_page' => $max, 'paged' => $page_num, 'post_type' => 'post', 'post_status' => 'publish');
    $search = new WP_Query($search_query);

    //use the object created, have_posts() alone will use global $wp_query
    if ($search->have_posts())
    {
            //The variables required to figure out next or previous page
            //Total number of post that match $s
        $total = $search->found_posts;
            //Post count for the page you're on
        $post_count = $search->post_count;
            //The maximum amount of pages to display all of the post results
        $page_count = ceil($search->max_num_pages);

        while ($search->have_posts())
        {
                    //Setup post data !important
            $search->the_post();

                    //Now your in the loop, use any loop functions you want
            $title = highlight(get_the_title(), $s);
        }
        $html = "<div id='news-page-nav'>";
            //Since we know what page we're on we know where to go
        $pre = $page_num - 1;
        $nex = $page_num + 1;
        if ($pre > 0)
        {
            $html .= "<span class='left fg-grey-light pointer' onclick='searchPosts(" . $pre . ");return false;' >P</span>";
        }
        if ($nex <= $page_count)
        {
            $html .= "<span class='right fg-grey-light pointer' onclick='searchPosts(" . $nex . ");return false;' >N</span>";
        }
        $html .= "</div>";
        echo $html;
    }
    else
    {
        echo false;
    }
    die();
}
function highlight($str, $mts)
{
    $keys = explode(" ", $mts);
    $title = preg_replace('/(' . implode('|', $keys) . ')/iu', '<span class="bg-highlight">\0</span>', $str);
    return $title;
}

I had to remind myself that, with AJAX, the page does not reload to serve up new content. Where one would have previous/next posts link I've created two 'links' that call the ajax function again but with a different page number. Now you can paginate search results without using WP's default url parameters. Something to keep in mind is how this will affect search engine results.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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