30

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
    )

)
  • Could you provide a dump of the result array for context? You might be able to pass it straight to theme_search_results – Clive Mar 20 '14 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()? – Garrett Albright Mar 20 '14 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 Mar 21 '14 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 – Agi Hammerthief Mar 28 '14 at 14:59
  • Have you used them in the situation I described in my question? – Jason Gray Mar 28 '14 at 19:05
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.

  • 1
    Was asked for a solution that explicitly didn't use pages or views – Daniel Waters Aug 5 '15 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 Aug 5 '15 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 Sep 26 '15 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
    Use form state redirects and not drupal_goto. – Kevin Apr 9 '17 at 3:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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