I've been trying to find a solution for this problem from the forums couple of days already and can't believe no-one wouldn't have solved it already..

So basically: When I do a search, I get the search results page showing the title of the node, some content of the node including the highlighted search word, and then the information like this on another row:
content type - author - date - X comments - X attachments

How can I customize this output, since I wouldn't like it to show the content type or the attachments, neither the amount of comments?

Comments

sin’s picture

Look at function theme_search_item($item, $type) in search.module.
It outputs a single search result.
Override this function in your theme as you need (copy/paste and remove $info[] = $item['type'] and $info = array_merge($info, $item['extra'])).

tormu’s picture

Thanks sin, that does it, great!

Just to clear up the instructions for other people like me that might have to wonder a bit before finally getting it working ;)

Put this in the template.php in theme-folder:

function phptemplate_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']) {
		//Don't output the node type
		//$info[] = $item['type'];
	}
	if ($item['user']) {
		$info[] = $item['user'];
	}
	if ($item['date']) {
		$info[] = format_date($item['date'], 'small');
	}
	if (is_array($item['extra'])) {
		//Don't output the extra information about the node (comments, attachments)
		//$info = array_merge($info, $item['extra']);
	}
	$output .= ' <dd>'. ($item['snippet'] ? '<p>'. $item['snippet'] . '</p>' : '') . '<p class="search-info">' . implode(' - ', $info) .'</p></dd>';
	return $output;
}

Another question that someone might have an answer: How to block some content type completely from the search? The advanced search is disabled and people doing the search can search for example images as well, and images are something that I'd rather not have on the search results..

sin’s picture

but have a question: how you disable advanced search? :)

tormu’s picture

mechler’s picture

You can disable Advanced Search with permissions (at least in Drupal 6).

Web Developer, Iowa State University College of Veterinary Medicine

markdingemanse’s picture

Just a note for users of the Smarty Theme Engine: this clean solution works for Smarty too. Just replace phptemplate with smarty in the function name, and place the function in YOURTHEME/smartytemplate.php.

mrgoltra’s picture

but what if I want to show post with attached picture and/or video (not the actual image itself)? Maybe add this option? Can anyone suggest how this can be done?

for example I want the search summary output to include

Node Title
Date posted
Location:
Contains: Video
Contains: Image

I am learning as I go. I am a noob.

Thank you,

Mark

remtheory’s picture

This is exactly what I need, except for 5.x. Can someone provide a snippet for that?

Thanks!!

tormu’s picture

I think it works pretty much the same with 5 - I did the just same thing with 5.3 few days ago:
template.php in the theme folder contains this (well some other stuff also, but I cut out the proprietary stuff).. the $item contains the search result item and the $output contains what will be shown eventually, so mess around with them.

//Theme the search results
function phptemplate_search_item($item, $type)
{
	$node_id = $item['node']->nid;
	//Print the result, if the result is NOT the frontpage, since we don't want the frontpage to appear on results.
	if($node_id != 59)
	{
		//Remove author information, since it's always admin in our case
		unset($item['user']);
		
		if($item['type'] != "image")
			$output = " <dt class=\"title\"><a href=\"" . check_url($item['link']) . "\">" . check_plain($item['title']) . "</a></dt>";
		
		$info = array();
		
		//Modify the date depending on the site language defined by i18n-module
		if ($item['date'])
			$info[] = custom_date_function_on_our_own_module($item['date'], i18n_get_lang());
		
		$output .= ' <dd>'. ($item['snippet'] ? $item['snippet'] : '') . '<p class="search-info">' . implode(' - ', $info) .'</p></dd>';
		
		//If the node type is image, don't print the result. I don't know how to exclude some node types from the search, so this is an ugly way
		if ($item['type'] == "image")
			$output = "";
			
		return $output;
	}
}
remtheory’s picture

Sorry I was being a spaz. Thanks for the help!

thomasmurphy’s picture

I'm trying to modify the 5.x search function to substitute the node created date, which comes from a DB import so they are all the same, to the node authored date. I think the line in theme_search_item I want to change in template.php is

if ($item['date']) {
$info[] = format_date($item['date'], 'small');
}

but what should this be instead?

tormu’s picture

What's the "node authored date"? Why don't you set the creation date of the node while importing from the database, so they wouldn't be all the same?
However, you should check what $item['node'] contains with print_r($item['node']); - see if it contains the "authored date" you are looking for.

mechler’s picture

Is this supposed to work with Drupal 6? I'm trying to use this but it doesn't seem to be working. I am using phptemplate and it's in my template.php file in the theme folder. I've cleared the cache just in case, though I don't think that should matter here. I thought I remembered something about Drupal 6 changing the way that you would do things like this.

Web Developer, Iowa State University College of Veterinary Medicine

sin’s picture

template.php is redundant in D6. Core modules, including search, moved most themable output to tpl files in their directories. Just look at /modules/search directory in your Drupal path, find .tpl.php file you need to override (I guess it is search-result.tpl.php), copy it to your theme folder, alter the copy in text editor as you like, clear cache.

Hayakawa’s picture

thanks

steingard’s picture

I am developing a product catalogue (not ecommerce) and I need the product's teaser thumbnail image to appear in the search results along with the text keywords.

Anyone have an idea on how I can display the image from a product's teaser CCK imagefield in the search results?

sin’s picture

See
http://api.drupal.org/api/4.7/function/hook_search_item
or
http://api.drupal.org/api/4.7/function/theme_search_item
where you can build custom search result item by adding picture from CCK field, you may be have to parse link url to get node id.
I have no deep knowledge about CCK inner working so can't help further. Please post back your results. Thanks!

steingard’s picture

Hey, thanks.

Yeah... I've got a basic understanding of PHP to begin with nevermind the 'inner workings' of CCK... but thank you very much for your insight. I'll read these links you gave me and get together with a programmer friend to see what we can come up with.

Thanks again :)

steingard’s picture

I had a friend of mine look at how Drupal outputs item content in an array, and he says it's pretty messy... but after a few hours of trying to weed through the array that turns into an object with an array inside half way through, his solution was as follows:

$imgobject = $item['node'];
$imageurl = $imgobject->field_product_teaser_image;

    $output = '<img src="/' . $imageurl[0]['filepath'] . '" alt="" />'

I put this bit in with the search results snippet as listed above (in template.php) and it worked out nicely. Now I just need to figure out how to grab the ALT information so that it's valid XHTML.

-Cheers

sin’s picture

Try

print_r($imageurl[0]);

to output field array, maybe this will help to find 'alt' tag.

Rhino’s picture

I'm looking to retrieve any images in a post before the

and return that in the search results, but I'm not sure how to adapt this in order to do so. Can anyone help me?

divad’s picture

Steingard, I wonder if you or someone else might be able to help me figure out a way, with the information you provided above, to amend the code below (which resides in my template.php file) so that I can generate search results with a thumbnail image included. The content I am searching against has a CCK imagefield in it. My code is a copy of what was provided at the top of this thread (see below).

I guess my question is, where do I put the code you supplied to make your image display? Thank you.

function newsflash_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']) {
        //Don't output the node type
        //$info[] = $item['type'];
    }
    if ($item['user']) {
        $info[] = $item['user'];
    }
   if ($item['date']) {
        $info[] = format_date($item['date'], 'small');
    }
    if (is_array($item['extra'])) {
        //Don't output the extra information about the node (comments, attachments)
        //$info = array_merge($info, $item['extra']);
    }
    $output .= ' <dd>'. ($item['snippet'] ? '<p>'.  $item['snippet'] . '</p>' : '') . '<p class="search-info">' . implode(' - ', $info) .'</p></dd>';
    return $output;
}
tormu’s picture

The following will get also a lot of things about the node that you don't need, so it might use up resources more than you know.

//This line will load all details of the found node into an object $found_node. The parameter for the node_load() has to be the nid of the search item, most likely $item['nid'], not sure about it though.
$found_node = node_load($node_id);
//The following line appends the CCK fields into the $found_node. If this line doesn't appear, the $found_node doesn't have the imagefield at all. Be aware that you don't need to run it like $found_node = node_invok...... - just as below.
node_invoke_nodeapi($found_node, 'view');
//After these couple of lines the $found_node should include your image, so the following should add the image to your results. Remember to replace the FIELDNAME :)
$output .= $found_node->field_FIELDNAME[0]['view'];

Remember: node_load() and node_invoke_nodeapi() may take resources more than the server can handle, so you should first enable Devel module to see how much the page generation time is for a certain search before applying the image addition. Refresh the same search a few times to get a good assumption on how much time it takes and then make the changes. Then refresh the same search again multiple times and see if the page generation time rises much. If not, it's ok. If it goes up like 1000ms for a full search page, then it might be that you need to find an alternate way that doesn't do so much unneeded things while getting the image data.

pwhite’s picture

Unfortunately nid is not in the item list

http://api.drupal.org/api/function/theme_search_item/5

I've been trying to find way to theme search results for an ecommerce site with little luck - any ideas?

pwhite’s picture

I solved the problem in the end by using the faceted search module

http://drupal.org/project/faceted_search

This allows you to use the views module to theme search results to display like products.

tormu’s picture

I'd say this does give the item's nid, though I can test it at the moment to be absolutely sure.

$node_id = $item['node']->nid;
jenlampton’s picture

I wanted my search results to include some additional information (from user profiles in my case, not CCK) so I ended up doing a MySQL querry to retrieve the information I needed. I used the phptemplate override of theme_search_item in my template.php. I'm not sure if this is entirely kosher, but it works for me. (Please note that this querry is dependent my DB values, and yours may be different. Check your own via myPhpAdmin before you run this code on your own system!)

function phptemplate_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[] = $item['type'];
    }
    if ($item['user']) {
		// change user log in to user name
		$JensQuerry = 'SELECT value FROM profile_values pv WHERE fid = 1 AND uid = '.$item['node']->uid;
		$jensName = db_result(db_query($JensQuerry));
		$item['user'] = $jensName;
		$info[] = $item['user'];
    }
    if ($item['date']) {
		// use published date instead of updated date
		$jensDate = $item['node']->created;
		$item['date'] = $jensDate;
		// reformat date to site standard
		if (date('m', $item['date'])== '05'){
			  $item['date'] = date("M d, Y", $item['date']);
			} else {
			  $item['date'] = date("M. d, Y", $item['date']);
			}
        $info[] = $item['date'];
    }
    if (is_array($item['extra'])) {
        $info = array_merge($info, $item['extra']);
    }
    $output .= ' <dd>'. ($item['snippet'] ? '<p class="snip">'. $item['snippet'] . '</p>' : '') . '<p class="search-info">' . implode(' - ', $info) .'</p></dd>';
    return $output;
}

I also changed the date and date format in here, but you can ignore that. Good Luck!

*~ current project: www.customerthink.com ~*

adonis_raduca’s picture

I added the search_config module in my Drupal instalation and I disabled the advanced search.
The advanced search dissapear from the search-result page output, but the search box is still there.
How can I remove this search box from the search-result page output? :)

mishhh’s picture

I tell you how I did it in my site:

1. go to themes configuration and remove the search box from your theme
2. go to blocks configuration and enable the "search form" block (then hit "save blocks" button)
3. then go to "search form" block again, hit configure link, and in the section "Show block on specific pages:" add in the Pages textarea the following:

search/*

That's it... no more search form on search pages...
:)

xaler’s picture

When I look at some ads I found with the search function, I see some Status info and also 'content type - author - date - X comments - X attachments'

I want to hide / delete these details, I think I must follow the same procedure but I cannot find a solution.

I think I must look at the ad module, find the themable details and put those in my theme file (without the content which should not be visible).

Sorry for my poor English, it's hard for me to explain in a foreign language.

sin’s picture

So no need to theme another function. phptemplate_search_item function, described above, is executed after all modules (including ad) added their extra info to search item. So you have to unset some fields in $info['extra'] array. You may see all of them with print_r($info['extra']) and unset inserting unset($info['extra']['my_example_field']) into phptemplate_search_item function.

Zoologico’s picture

Thanks.

Jenzen-1’s picture

Hello,
its possible to block some profile fields?
I had installed "profile-plus-modul" can i edit the profileplus.module to block some fields (for example: name or age)?

Target: if one user write "male" in the search box -> no output of all "male" users

Thanks for helping!!

Greetings from Germany!

tormu’s picture

Sounds like something I would be implementing in the future too, so I searched a bit..
I've done it already that for example image nodes are not searchable (removed from the search index), so the hook_update_index() is the key.
You have to implement hook_update_index in your own module and in it somehow you have to find the nodes/users you want to exclude things for and then update the search index with new data (that don't have the name or age anymore).
To get you started: http://drupal.org/node/170605

enkara’s picture

In wich part of the page.tpl.php do I have to paste this? It doesn't work for me...

ssn’s picture

hi buddies..

the info submitted here is very useful. i need help to show total no of items on the search page.
e.g. Total items found: 158 etc.

Many thanks in advance.

cameron tod’s picture

I figured this out by trawling through search.module. Try adding this to one of your theme functions:

 $results_count = current(db_fetch_array(db_query("SELECT count(*) as results_count FROM temp_search_results")));

Now $results_count will be the total number of items returned by the search, and you can use it in your theme as you see fit.