Last updated February 5, 2012. Created by ugerhard on September 12, 2007.
Edited by jhodgdon, mikey_p, bekasu, ShawnP. 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 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_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:
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!
Comments
Showing Result Count and Result Range in Drupal 5
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.
<?phpfunction 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
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
DrupalEasy
It would be awesome if
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
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:
<?phpglobal $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?
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?
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...
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,
Oh ok. Yes, search-results.tpl.php is for the entire search results page. search-result.tpl.php is for each search result.
Google-like search results "Displaying 1-10 of 10" for Drupal 6
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.
Works in D7 too
Thanks!
Extra Search Form Found with Search Results Page
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!
don't think you can get rid of it beyond using style
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! ;)
It worked
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.
There has to be a better way
There has to be a better way to fix this. Hiding things with CSS doesn't seem sustainable. Maybe a preprocess function somewhere?
A mediocre alternative
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...
Drupal 6 Solution
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!
it's a good solution for views
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/
It's easy and follows Drupal standards
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;
}
}
where this code go? on the
where this code go? on the template? or do i have to create a *.module?
Since the function is
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 :-(Kefk | CineDat | Fotonexus | Encycan | Encymus | Taxidi
I was able to get it working
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?
Needs update for Drupal 7
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.