Customize the search results page

Last modified: February 21, 2008 - 11:55

Do you need to change the content shown in the results of the Drupal search? It is imperative to do this in the Drupal way, and it is most helpful to understand the thought process of doing such a procedure. Following is an example of how to customize the Drupal search results from more than just a technical aspect but also from the thought process required. This same thinking can be done when having to customize other components within Drupal framework.

The first step is to find out what is driving the Drupal search. In the modules directory you will see the search folder which is a pretty good indication that this is what drives the Drupal search. Now, open the search module folder to see what is inside and what will be there to customize, keeping in mind that you will not actually be doing any changes to any files in the search module itself.

Inside the search module you will find the standard .info, .install, .module and a .css file. In this case you will be looking at the search.module itself. What you are looking for is something you can hook into or theme. The functions you are looking for are theme_ functions and in the search module you will find theme_search_theme_form, theme_search_block_form, theme_search_item and theme_search_page. You will be able to customize any one of these functions in a way that will not touch the actual Drupal core module. Great!

In this example you are going to change the look of the search result page (or srp to all those seo gurus). We are going to remove the line of info that tells who wrote the node, when it was written, comments etc... From first glance it may be a good assumption that the theme_search_page function is the one to customize from within my own theme. For this example we will use the zen theme that would be located in your /sites/all/themes/zen folder. Here is the theme_search_page which is nicely commented so you can see the parameters, and purpose of this function.

/**
* Format the result page of a search query.
*
* Modules may implement hook_search_page() in order to override this default
* function to display search results. In that case it is expected they provide
* their own themeable functions.
*
* @param $results
*   All search result as returned by hook_search().
* @param $type
*   The type of item found, such as "user" or "node".
*
* @ingroup themeable
*/
function theme_search_page($results, $type) {
  $output = '<dl class="search-results">';

  foreach ($results as $entry) {
    $output .= theme('search_item', $entry, $type);
  }
  $output .= '</dl>';
  $output .= theme('pager', NULL, 10, 0);

  return $output;
}

After looking more closely you will notice that this function calls the theme_search_items function by way of theme('search_item', $entry, $type) so you now see that this is actually the function that you want to manipulate. This function looks like the following:

function theme_search_item($item, $type) {
  $output = ' <dt class="title"><a href="'. check_url($item['link']) .'">'. check_plain($item['title']) .'</a></dt>';
  $info = array();
  if ($item['type']) {
    $info[] = check_plain($item['type']);
  }
  if ($item['user']) {
    $info[] = $item['user'];
  }
  if ($item['date']) {
    $info[] = format_date($item['date'], 'small');
  }
  if (is_array($item['extra'])) {
    $info = array_merge($info, $item['extra']);
  }
  $output .= ' <dd>'. ($item['snippet'] ? '<p>'. $item['snippet'] .'</p>' : '') .'<p class="search-info">'. implode(' - ', $info) .'</p></dd>';
  return $output;
}

So what you will do next is to copy all of the above function directly into my template.php file that is found in the /sites/all/themes/zen folder. The template.php file is what you can use in order to indirectly manipulate core Drupal. Not just for search, but for all core modules. Then change the name of the theme_search_item($item, $type) function to zen_search_item($item, $type). After saving the file, Drupal no longer calls search modules function but now calls your newly created theme zen_search_item function. Simply awsome, and now when you have to do a core drupal update, your changes in the theme will not be over written when a core search module update is performed.

Don't forget to change the name of your template.php function or you may get the following error. "Fatal error: Cannot redeclare theme_search_item() (previously declared in....)" I just saying ... this didn't happen to me ;)

Now, lets get to the really good stuff. Because this new zen_search_item() function is in your theme, you are pretty free to do whatever you need in order to get the results you desire. So, my quick change of removing the extra info mentioned previously can be accomplished by removing the code that contains the extra data that you don't need. Your new function in your template.php file now becomes:

function zen_search_item($item, $type) {
  $output = ' <dt class="title"><a href="'. check_url($item['link']) .'">'. check_plain($item['title']) .'</a></dt>';
  $output .= ' <dd>'. ($item['snippet'] ? '<p>'. $item['snippet'] .'</p>' : '');
  return $output;
}

So, you can see that you removed a lot of info but at this point you can go both ways. You can add content, change the elements or do whatever you desire, without editing core Drupal!

Showing Result Count and Result Range in Drupal 5

butterfi - August 29, 2008 - 23:23

We wanted Google-like search results, e.g. "1-10 of about 100 for 'foo'". Here's what I did:

What was helpful was when I realized that search doesn't return the entire found set, instead it returns: the number of pages in the found set ($pager_total); the page number that you're on ($pager_page_array); and the actual results for that search page ($results). Given those numbers, we can calculate how many search results we have based on the number of returned pages. For result pages that have less then a whole page, like a search with just a few hits, or the last page of a found set of results, we count the $results array for more accurate reporting.

<?php
function theme_search_page($results, $type) {
  global
$pager_page_array, $pager_total;
 
$output = '';
 
//establish page variables
 
$total_pages = $pager_total['0'];
 
$total_page_count = $total_pages - 1;
 
//approx number of results based on page count
 
$approx_results = $total_pages * 10;
 
//calculate range
 
$page_number = $pager_page_array['0'];
 
$start_result = $page_number * 10 + 1;
 
$end_result = $page_number * 10 + 10;
 
//get search term
 
$search_term = arg(2);
 
//remove page numbers and plus signs
 
$search_term = explode('?', $search_term);
 
$search_words = $search_term['0'];
 
//check for a single page of results and count array
 
if($total_pages == '1') {
   
$found_set = count($results);
   
$output .= '<div id="page_results">';
   
$output .= ': '. $start_result .' - '. $found_set .' of '. $found_set .' for "'. $search_words .'"';
   
$output .= '</div>';
  }
  elseif (
$page_number == $total_page_count) {
   
$found_set = count($results);
   
$adjusted_end = $total_page_count * 10 + $found_set;
   
$output .= '<div id="page_results">';
   
$output .= ': '. $start_result .' - '. $adjusted_end .' of '. $adjusted_end .' for "'. $search_words.'"';
   
$output .= '</div>';
  }
  else {
 
$output .= '<div id="page_results">';
 
$output .= ': '. $start_result .' - '. $end_result .' of about '. $approx_results .' for "'. $search_words .'"';
 
$output .= '</div>';
  }
 
$output .= '<div id="search_page">';
 
$output .= '<dl class="search-results">';
  foreach (
$results as $entry) {
   
$output .= theme('search_item', $entry, $type);
  }
 
$output .= '</dl>';
 
$output .= theme('pager', NULL, 10, 0);
 
$output .= '</div>';
  return
$output;
}
?>

Hope that helps!

Here's one that may be a

liberatr - September 25, 2008 - 21:05

Here's one that may be a little simpler:

<?php
function blueprint_search_page($results, $type) {
  global
$pager_page_array, $pager_total;
 
 
$default_results = 10;
 
$count = (count($results) == $default_results)? $default_results: count($results);
 
$first_result = $pager_page_array[0] * $default_results;
 
 
$output = '';
  if((
$pager_total[0] > 1) && ($pager_page_array[0] == $pager_total[0])) {
   
$count_total = sprintf(' of about %d', $default_results * $pager_total[0]);
  }
 
$output .= '<p class="search-count-results">'.sprintf('Showing results %d to %d%s', $first_result + 1, $first_result + $count, $count_total).'</p>';
 
$output .= '<dl class="search-results">';

  foreach (
$results as $entry) {
   
$output .= theme('search_item', $entry, $type);
  }
 
$output .= '</dl>';
 
$output .= theme('pager', NULL, 10, 0);

  return
$output;
}
?>

Ryan Price
Florida Creatives

Both codes work absolutely

wflorian - March 5, 2009 - 10:45

Both codes work absolutely fine with D5. But how can I change number of search results shown on every page? Right now there are shown 10 results per page. I would like to have 20 results on every page.

Changing "$default_results = 10;" to "$default_results = 20;" didn't work...

Drupal 6

davexd - January 12, 2009 - 03:24

I'm having no luck. Would this work the same in Drupal 6?

don't think so

mray - January 16, 2009 - 10:59

I think I followed these steps and end up with a wrong behaviour.
The codesnippet from the template.php always directly shows up on every generated page (and destroying the layout)

It would be awesome if

shevot - March 5, 2009 - 22:09

It would be awesome if someone could give these instructions for Drupal 6. It seems that there are a lot of use here that need because it has been addressed several times with no solution given. Thanks

Total number of search results in Drupal 6

matteusx - April 25, 2009 - 03:12

Similar to the Drupal 5 solutions, this taps into the pager to find the count. However, it looks to me like D6 has a new global $pager_total_items which makes this simple. In my search-results.tpl.php I add:

<?php
 
global $pager_total_items;
?>

and then use:

Your search returned <?php print format_plural($pager_total_items[0], '1 result', '@count results'); ?>.

I didn't need, and didn't figure out, how to show text like "Viewing results 11 to 20 of 99 total." This could be calculated using $pager_page_array and $pager_total like in the Drupal 5 examples, but you'll still have to provide the number of results per page.

More on the global variables here: http://api.drupal.org/api/globals

an error?

avolve - May 16, 2009 - 10:01

I tested this snippet for a site.

Your search returned <?php print format_plural($pager_total_items[0], '1 result', '@count results'); ?>.

I added it to a custom search-result.tpl.php, though no value is returned for the number of results (@count). A search with multiple results and a search with a single results yielded 'Your search returned results'

global?

matteusx - June 1, 2009 - 15:30

Did you make sure to add the global $pager_total_items somewhere before the PHP code? It's the first snippet of code in my earlier post.

repeated...

avolve - June 2, 2009 - 05:01

I had made a error in the code (your snippet works fine). I had not yet posted a follow-up/correction.

Inserting the snippet into the search-result.tpl.php file has the snippet repeated for every search result rather than just at the top.

Oh ok. Yes,

matteusx - June 2, 2009 - 15:22

Oh ok. Yes, search-results.tpl.php is for the entire search results page. search-result.tpl.php is for each search result.

I'm using Drupal 6.x and none

Iulian81 - June 16, 2009 - 14:48

I'm using Drupal 6.x and none of this works. Maybe it is just for the versions 5.x. I think it simply does not recognize the function I insert in Template.php ! I tried to make my search results show thumbnails and to erase the date, time and user. The search.module file even do not contains the function theme_search_items that I understand it must have!

Drupal 6

jeffschuler - June 27, 2009 - 06:36

Customizing search results is even easier in Drupal 6.

Use search-result.tpl.php to override how individual search results are displayed, and search-results.tpl.php for overriding the whole list of results.

Just copy [the source code from] the template file you wish to override -- into a file of the same name in your theme directory, then edit as necessary.

 
 

Drupal is a registered trademark of Dries Buytaert.