8

I would like to add/inject/append extra results into the WordPress search results.

At the moment WordPress only allows you to "adjust" the query that is being executed on its own database, but doesn't allow you to modify (or in WordPress lingo, filter) the results array.

I.e: If in WordPress I search for the term 'potato' all posts related to this term come back. I want to include results that I've obtained via a different service into the WordPress results set.

Just to clarify, I'm getting my results from a 3rd party API call. Not from the WordPress database.

Does anyone have an idea on how I can do this?

Edit: Preferably this needs to happen in my WordPress plugin without having to change search templates.

Ruben
  • 1,427
  • 3
  • 17
  • 25
  • If you want just to append the new results, why not call a function that adds the new results after? – Ricardo Nuñez Jun 13 '14 at 00:37
  • Edit your search.php page template and iterate over the other results data you have before the main Wordpress loop. Or, use the Wordpress loop to create a similar array of data and combine them. – ssergei Jun 13 '14 at 00:37
  • if you provide more info i can solve this for you. WP_QUERY and the loop are obviously limited to wp but you can of course add to the query object manually after WP_QUERY as @ricardo Nunez suggested, what info/filter do you want to add? – David Jun 13 '14 at 01:32
  • Thanks for your responses all. The type of filter (or action) I'm looking for simply allows me to append results to the list of posts that WordPress returns. The results I want to add come from an API call that is querying a different service so not a WordPress install. I hope this is clear enough. In short: I want to add non WordPress search results to the WordPress search results. – Ruben Jun 13 '14 at 01:37

2 Answers2

11

You can use pre_get_posts to add/edit your search result without changing things is search template.

To exclude pages

To exclude pages in your search results. It is possible to create an action hook that limits the search results by showing only results from posts.

The following example demonstrates how to do that:

function search_filter($query) {
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_search) {
      $query->set('post_type', 'post');
    }
  }
}

add_action('pre_get_posts','search_filter');

Include Custom Post Types in Search Results

function search_filter($query) {
  if ( !is_admin() && $query->is_main_query() ) {
    if ($query->is_search) {
      $query->set('post_type', array( 'post', 'movie' ) );
    }
  }
}

add_action('pre_get_posts','search_filter');

Include Custom / API Results

function search_filter() {
    if ( is_search() ) {
        // Do your API call here
        // Save retrieved data in your wordpress
        // This will also help to you avoid api call for repeated queries.
        $post_id = wp_insert_post( $post, $wp_error ); // wp_insert_post() // Programatically insert queries result into your wordpress database
        array_push( $query->api, $post_id );
    }
}
add_action('pre_get_posts','search_filter');    
function have_posts_override(){
    if ( is_search() ) {
        global $wp_query;
        $api_post = $wp_query->api;
        foreach ($api_post as $key) {
        // This will enable you to add results you received using API call
        // into default search results.
            array_push($wp_query->posts, $key); 
        }
    }
}
add_action( 'found_posts', 'have_posts_override' );

Reference:

Abhineet Verma
  • 1,008
  • 8
  • 18
  • Thanks @Abhineet, I've indeed looked at pre_get_posts but unfortunately this function only works when trying to retrieve results from the WordPress back end. I'm obtaining my search results from a 3rd party API call and want to add these to the already existing results array. – Ruben Jun 16 '14 at 00:01
  • 1
    @Ruben It's easy, efficient and better for search results if you save data in your wordpress after getting it using API call. But if you want to make api call on every request even for repetitive request then it'll be bit tricky to implement that. But logic would be similar to the one i just updated. – Abhineet Verma Jun 16 '14 at 19:27
  • 1
    thanks heaps for your response. The code would probably work but it's not the solution I'm looking for. I simply want to look at the array and append or remove elements just before they are printed out. The wp_insert_post is a nice workaround for my problem but I don't think its a good long term solution. Especially because I'm dealing with quite dynamic search results and I'm afraid I'll be slowing thing down significantly. Thanks for your response though. I'll mark it as a correct answer because it might help other people who can use it. – Ruben Jun 26 '14 at 00:31
5

The question might be old, but I had a similar problem and someone in the future maybe as well, so I'll post my (better) solution.

As said above, it would have been the cleanest solution to save the api query results in the wp_posts-table (as a custom post type maybe) and perform a normal WP-Search on them.

But in my case I had to deal with another table which cached some external data and link it to IDs of existing posts and I could not change this structure.

Therefore the Solution of Abhineet Verma (search_filter + pre_get_posts) seemed useful at first, but in the end it was not suitable for me. I was able to add additional posts to the query result, but they don't fit into the normal pagination of the results. For example, If you want to display 10 results per page and use the solution above and get twenty results from the api, you would have 30 results per page: the ten normal results, which belong to the page plus all twenty on every page. It also breaks some pagination-plugins.

So I finally solved the problem as follows. I used the filter posts_search to extend the sql-query:

add_filter('posts_search', function($sql) {

    if (!$sql) {
        return $sql;
    }

    global $wpdb;
    $sqst = "select id from {$wpdb->prefix}mytable ... bla bla ->  query to my custom table, wich return a bunch of IDs";
    $sqlr = "AND (({$wpdb->prefix}posts.ID in ($sqst)) or (1 = 1 $sql))";

    return $sqlr;

});

It looks a little bit strange but works very good. Maybe it will help someone sometimes!

Paflow
  • 2,030
  • 3
  • 30
  • 50