Last updated December 6, 2013. Created on September 12, 2007.
Edited by saraswata, LeeHunter, drupalshrek, xamount. Log in to edit this page.

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
Inside the search module you will find the standard t 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.
';

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

return $output;
}
?>

After looking more closely you will notice that this function calls the theme_search_item 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:

<?php
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'm 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:

<?php
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!

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.

Comments

butterfi’s picture

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!

liberatr’s picture

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
Blink ReactionDrupalEasy Podcast

shevot’s picture

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

msielski’s picture

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

avolve’s picture

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'

avolve designs | ethical by design

msielski’s picture

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.

avolve’s picture

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.

avolve designs | ethical by design

msielski’s picture

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

KarimB’s picture

Just want to add that you can show the number of results displayed on the page like Displaying 1-10 of 249", adding the following code at the top of your search-results.tpl.php (yes, search-results with a “s”).

The $results_per_page has to be set manually according to your settings.

<?php
global $pager_page_array, $pager_total, $pager_total_items;


if (
$pager_total_items <> 0){
 
$results_per_page=10;
 
$from = 1+(($pager_page_array[0])*$results_per_page);
  if ( (
$pager_page_array[0]+1) == $pager_total[0]){
   
// we are on the last page
   
$to =   $pager_total_items[0]; 
  }
  else {
   
$to = 1+(($pager_page_array[0])*$results_per_page)+$results_per_page-1;
  }
  print
"Displaying $from - $to of ".format_plural($pager_total_items[0], '1 result', '@count results');
}
?>

Hope this help.

More in my Drupal Blog: http://www.webenstock.com

David Vespoli’s picture

Thanks!

johnvsc’s picture

For a multi-language site, substitute the following snippet for the "print" line:

  $output = t('Displaying %from - %to of %number', array('%from'  => $from,
                                                        '%to'     => $to,
                                                        '%number' => format_plural($pager_total_items[0], '1 result', '@count results')
                                                   ));
  ;
  print $output;

- johnvsc

lthoughton’s picture

Hi all,

I have a site that contains the search block in the upper right-hand corner of the page. When search results are displayed, there is an extra search form within the results node beginning with "Enter your Keywords" and another search box to do yet another search. The box seems to be coming from the core search module function search_form. I haven't been able to find anything on hiding that extra box. It seems redundant when you have the search block already in place. Is there any way to hide this extra search form from view in the results page? Thanks!

yakker’s picture

From what I remember when I dug around, the Search module prints the form directly, between the title and content elements of the page, so unless you hack the core module yourself, there's no way to stop this extra form from printing (could be wrong about this, but that's the conclusion I came to after looking at the search.module code).

But, if you don't mind knowing that the extraneous code is there, you could find a way to hide it with CSS. The form has an id="search-form". Your block level search form should have a different one (I think "search-block-form"). In style.css, add this:

#search-form{
display:none;
}

That would hide the search form EVERY time it appeared in the body of your site. If you wanted to only hit the search page, you should be able to target it specfically by employing the page class that gets written to it by drupal: .page-search. So:

.page-search #search-form{
display:none;
}

Personally, whether it's due to a meaningful attachment to elegant markup, or whether it's because I'm neurotic, I can't stand knowing that <form> is sitting there in the page and just "not" being displayed. ;)

...neurotic, i'm pretty sure.

Addendum: I haven't tried this myself, but I've done similar things to move the comment form around (which suffers from the same sort of issue). Anyone who knows this is a bad idea, please say so! ;)

lthoughton’s picture

That was a simple fix to the problem. Thanks! As long as Drupal doesn't break its back calling the form function, I'm happy with hiding it.

obrigado’s picture

There has to be a better way to fix this. Hiding things with CSS doesn't seem sustainable. Maybe a preprocess function somewhere?

obrigado’s picture

This is just as vulgar conceptually, but at least it stops the HTML before it leaves the server. Drop it into your theme's template_preprocess_page function:

if (arg(0) == 'search') {
$vars['content'] = preg_replace('/<form action="\/search\/node".*<\/form>/s', '', $vars['content']);
}

Still looking for a more 'drupal' way to do this...

mbelos’s picture

Hey guys, a Drupal 6 solution is to override the default 'views-view' template file. Copy the 'sites/all/modules/views/theme/views-view.tpl.php' file to your theme folder (changing the filename to: 'views-view--.tpl.php') and delete the following lines (approx. lines 35-39):

<?php if ($exposed): ?>
  <div class="view-filters">
    <?php print $exposed; ?>
  </div>
<?php endif; ?>

Clear your cache, and refresh!

---
Funke Labs
W: http://www.funkelabs.com.au
Ultimo, NSW, Australia

bricef’s picture

It don't work for the build in search result page, because it's not using views.

My blog http://pelmel.org/
I'm currently working for SQLI http://www.sqli.com/

rsorokine’s picture

This gets rid of the content of the form, but not of the <div> containing some hidden fields. Hope this will help.

/**
* Implementation of hook_form_alter() for the Search Block
*
*/

function yourmodule_form_alter(&$form, &$form_state, $form_id) {
  switch ($form_id) {

  // Hide Search form on Search Result page
    case 'search_form':
  unset($form['basic']);
  unset($form['advanced']);
  break;
  }
}

Haidee’s picture

where this code go? on the template? or do i have to create a *.module?

asb’s picture

Since the function is referring to yourmodule, this snippet is probaly intended to go into a custom module. However, I'd like to put this function into template.php, but that doesn't seem to work :-(

dayer4b’s picture

I was able to get it working in template.php :

function template_form_search_form_alter(&$form, &$form_state, $form_id) {
    unset($form['basic']);
    unset($form['advanced']);
}

I'm not quite satisfied with this either, though. There should be a way to remove the entire form, instead of just the visible parts. I don't want users with assistive technologies getting lost when they find this search form without any useful input fields.

Any ideas?

commonpike’s picture

function YOURTHEME_form_search_form_alter(&$form, &$form_state) {
// Remove the search form from search result
        // page if there are results
if (arg(1) == 'node' && arg(2) != NULL) {
$form['#access'] = FALSE;
}
}

*-pike

jhodgdon’s picture

The format_date() function has changed in Drupal 7 and this page needs an update. See #221006: Handbook is not up to date on format_date for details.

loopduplicate’s picture

You can just use the templates that come with the search module located in /modules/search/
search-results.tpl.php
search-result.tpl.php

Copy those files into your theme folder and change the markup.

For more on using template suggestions, see:
Drupal 6 Template Suggestions ( http://drupal.org/node/1089642 )
Drupal 7 Template Suggestions ( http://drupal.org/node/1089656 )

soulston’s picture

You can use hook_page_alter: http://drupalcontrib.org/api/drupal/drupal%21modules%21system%21system.a...

/**
* implements hook_page_alter()
*
* Alter the page output before render.
*/
function NAME_OF_YOUR_THEME_page_alter(&$page) {
  // kpr($page); //use this to find the item you want to remove - you need the devel running.
  // Remove the search form from the search results page.
  if (arg(0) == 'search') {
    if (!empty($page['content']['system_main']['search_form'])) {
      hide($page['content']['system_main']['search_form']);
    }
  }
}

This should be placed in the template.php file of your theme.

b8x’s picture

in that module no such functtion (theme_search_page)! at least in d7 i can't see it.

pratik60’s picture