29

Problem: Need to run my own searches programmatically with Search API. Every google result I find is geared toward teaching non-developers how to use the module with Views with no results on doing it like I want.

Information:

  • Using local database service instead of Solr or any other.
  • Have data not stored in database that will appear alongside other results.
  • Content will be grouped in "type" tabs.
  • Not using Views for various reasons.
  • Have Facets API enabled but no clue how to use it either.

Why: Because I want to have the search page be at /site-search and without /node/keyword after the page argument. Also will be asked to customize this beyond the scope of other modules that may provide the same type of functionality. And I want to learn how to do this but have not found any tutorials or other insight on how to accomplish it.

The rest: I have created my search page and on it I am executing the search with:

$term = $_SESSION['my-search']['term'];
$server = search_api_server_load('database');
$index = search_api_index_load('default_node_index');
$query = new SearchApiQuery($index);
$query->keys($term); 
$query->fields(array('title','body:value')); 
$srv= new SearchApiDbService($server);
$result = $srv->search($query);

The session variable is set when a search form is submitted then redirects the user to /site-search to perform the search and show the results.

If I output $result I see it's an array with different information including a result set that is an array of node ids and their scores.

I could run through those, grabbing the node and displaying the results myself but I figure there's got to be some other method for rendering the results of the search. I haven't found it though and that's the problem.

I've been looking through the different classes in Search API and Facet API and can't find anything in them that seem like they would build result output.

Any help with this will be appreciated.

Results example:

Array
(
[result count] => 11
[results] => Array
    (
        [37] => Array
            (
                [id] => 37
                [score] => 15.7503318786621
            )

        [39] => Array
            (
                [id] => 39
                [score] => 7
            )

        [40] => Array
            (
                [id] => 40
                [score] => 5
            )

        [31] => Array
            (
                [id] => 31
                [score] => 4
            )

        [33] => Array
            (
                [id] => 33
                [score] => 1
            )

        [36] => Array
            (
                [id] => 36
                [score] => 1
            )

        [1] => Array
            (
                [id] => 1
                [score] => 1
            )

        [15] => Array
            (
                [id] => 15
                [score] => 1
            )

        [16] => Array
            (
                [id] => 16
                [score] => 1
            )

        [27] => Array
            (
                [id] => 27
                [score] => 1
            )

        [35] => Array
            (
                [id] => 35
                [score] => 0.980873763561249
            )

    )

[warnings] => Array
    (
    )

[ignored] => Array
    (
    )

[performance] => Array
    (
        [complete] => 0.0033111572265625
        [preprocessing] => 0.00053095817565918
        [execution] => 0.0027379989624023
        [postprocessing] => 4.2200088500977E-5
    )

)
7
  • Could you provide a dump of the result array for context? You might be able to pass it straight to theme_search_results
    – Clive
    Commented Mar 20, 2014 at 21:37
  • 1
    "I could run through those, grabbing the node and displaying the results myself but I figure there's got to be some other method for rendering the results of the search. I haven't found it though and that's the problem." -- node_view_multiple()? Commented Mar 20, 2014 at 22:40
  • Clive: I've updated my question with the output of the search results. Garrett: Thanks for pointing out that function, didn't know it existed. It'll be handy for some other projects but has no relevance to what I'm wanting to do here. :) There is supposed to be keyword highlighting and displaying of relevant search text in the Search API classes but I've been unable to figure out how to get the results to render using those methods. Thanks for the help so far! :)
    – Jason Gray
    Commented Mar 21, 2014 at 11:50
  • Have you tried looking at the search functions on the Drupal API? api.drupal.org/api/drupal/modules!search!search.module/7 Commented Mar 28, 2014 at 14:59
  • Have you used them in the situation I described in my question?
    – Jason Gray
    Commented Mar 28, 2014 at 19:05

2 Answers 2

4

Have you looked at the Search API pages module. It uses the Search API module and creates a custom search page. You could probably look at that module for clues on how to implement what you are trying to do. The module itself might even provide a lot of the functionality that you are looking for.

3
  • 1
    Was asked for a solution that explicitly didn't use pages or views Commented Aug 5, 2015 at 17:00
  • No he said "Not using Views for various reasons". The Search API module does not. Sorry if my suggestion didn't help
    – n30r3b3l
    Commented Aug 5, 2015 at 19:18
  • 2
    I would have to agree that Search API pages module is a good starting place! I've implemented a custom search before and used the code in there as a starting point, which can be done without using pages!
    – paaat
    Commented Sep 26, 2015 at 9:26
1

Here's my solution in about 100 lines -- a little simpler than pages...

define('SEARCH_QUERY_TERM', 'query');
define('SEARCH_PAGE_TERM', 'page');
define('SEARCH_LIMIT_TERM', 'limit');
define('SEARCH_DEFAULT_LIMIT', 10);

/**
 * Implements hook_menu().
 */
function my_module_menu() {
    $items['search'] = array(
        'title' => 'Search',
        'page callback' => 'my_module_page',
        'access callback' => TRUE,
        'type' => MENU_CALLBACK,
    );

    return $items;
}

/**
 * My Module Search Functions
 */

function my_module_page() {
    $build = array(
        'form' => drupal_get_form('my_module_form'),
        'results' => array('#theme_wrappers' => array('container')),
    );

    foreach (my_module_result() as $eid => $entity) {
        $build['results'][$eid] = entity_view('node', array($entity), 'teaser');
    }

    return $build;
}

function my_module_form($form, &$form_state) {
    list($query, $page, $limit) = my_module_params();

    $form['query'] = array(
        '#type' => 'textfield',
        '#title' => t('Search'),
        '#default_value' => $query,
    );
    $form['actions'] = array('#type' => 'actions');
    $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Search'),
    );

    return $form;
}

function my_module_form_submit($form, &$form_state) {
    $values = $form_state['values'];
    $query = isset($values['query']) ? $values['query'] : '';
    $form_state['redirect'] = array('search', array('query' => array('query' => $query)));
}

function my_module_params() {
    $query = '';
    $page_number = 0;
    $limit = SEARCH_DEFAULT_LIMIT;
    $params = drupal_get_query_parameters();

    if (isset($params[SEARCH_QUERY_TERM])) {
        $query = $params[SEARCH_QUERY_TERM];
    }
    if (isset($params[SEARCH_PAGE_TERM]) && is_numeric($params[SEARCH_PAGE_TERM])) {
        $page_number = $params[SEARCH_PAGE_TERM];
    }
    if (isset($params[SEARCH_LIMIT_TERM]) && is_numeric($params[SEARCH_LIMIT_TERM])) {
        $limit = $params[SEARCH_LIMIT_TERM];
    }

    return array($query, $page_number, $limit);
}

function my_module_result() {
    $index_id = 'default_node_index';

    list($keys, $page_number, $limit) = my_module_params();
    $offset = $limit * $page_number;

    $options = array(
        'search id' => 'node:default',
    );

    $query = search_api_query($index_id, $options)->keys($keys);

    if ($limit > 0) {
        $query->range($offset, $limit);
    }

    $results = $query->execute();
    $results = isset($results['results']) ? $results['results'] : array();

    return entity_load('node', array_keys($results));
}
1
  • 1
    Use form state redirects and not drupal_goto.
    – Kevin
    Commented Apr 9, 2017 at 3:41

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.