Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add results into WordPress search results

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.

like image 672
Ruben Avatar asked Jun 13 '14 00:06

Ruben


2 Answers

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:

  • Exclude_Pages_from_Search_Results

  • Include_Custom_Post_Types_in_Search_Results

like image 165
Abhineet Verma Avatar answered Sep 22 '22 13:09

Abhineet Verma


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!

like image 34
Paflow Avatar answered Sep 20 '22 13:09

Paflow