pict-drupal.png Drupal6の標準のSearchモジュールで提供されるサイト内検索は日本語で検索した場合にうまくいかない部分がいくつかあります。ここではその解消方法を紹介します。

何が問題なの?

Drupal6の標準のサイト検索は英語などの単語をスペースで区切る言語の場合は良いのですが日本語のように単語の区切りが明快でない言語の場合にうまくいかない部分があります。一番大きな問題はうまくANDやOR、NOTなどの論理演算条件に従った検索ができない点ですが、これはDrupalの標準のサイト検索ではどうにもなりません。サイト内検索にGoogleなどより高度な言語解析処理のできる検索を利用したり、その他Namazuなどの日本語に対応した全文検索エンジンを利用するしかないかと思いますが、この記事ではそれは対象外としています。あくまで簡単にできる範囲で現在の日本語での検索のうまくない部分を直したいと思います。

修正前
ss-search-jp-before.png
修正後
ss-search-jp-after.png
この上の2つを比べてもらうとわかるかと思いますが、以下の2点を今回修正します。

問題1)検索結果のページ説明文がちゃんと表示されないで「...  ...」だけになってしまう場合がある。

標準のSearchモジュールのコードを詳しく解析しないとはっきりとはわかりませんがこのモジュールのsearch_excerpt()関数が日本語の場合うまく動作しないことがあるからではないでしょうか。特定の記事でこの現象が発生するようです。

問題2)検索結果のページ説明文の中で検索キーワードがハイライト表示(<strong>タグによる)されない。

これはスペースで区切られた言語でのみうまくハイライト表示されるようなコードになっているからです。

解決法

リサーチしたり標準モジュールのコードを解析した結果、これらを解決する方法をモジュール化することは難しいという結論に達しました。これはうまいhook関数やテンプレート関数が実装されていないことによります。もちろん、Drupalのコアにパッチをあてる方法もありますが、これもできれば避けたいので、Searchモジュールの結果表示に使用するテンプレートを利用してなんとかすることにしました。

以下がそのテンプレートファイルです。
  1. <?php
  2. // $Id: search-result.tpl.php,v 1.1.2.1 2008/08/28 08:21:44 dries Exp $
  3.  
  4. /**
  5.  * @file search-result.tpl.php
  6.  * Default theme implementation for displaying a single search result.
  7.  *
  8.  * This template renders a single search result and is collected into
  9.  * search-results.tpl.php. This and the parent template are
  10.  * dependent to one another sharing the markup for definition lists.
  11.  *
  12.  * Available variables:
  13.  * - $url: URL of the result.
  14.  * - $title: Title of the result.
  15.  * - $snippet: A small preview of the result. Does not apply to user searches.
  16.  * - $info: String of all the meta information ready for print. Does not apply
  17.  *   to user searches.
  18.  * - $info_split: Contains same data as $info, split into a keyed array.
  19.  * - $type: The type of search, e.g., "node" or "user".
  20.  *
  21.  * Default keys within $info_split:
  22.  * - $info_split['type']: Node type.
  23.  * - $info_split['user']: Author of the node linked to users profile. Depends
  24.  *   on permission.
  25.  * - $info_split['date']: Last update of the node. Short formatted.
  26.  * - $info_split['comment']: Number of comments output as "% comments", %
  27.  *   being the count. Depends on comment.module.
  28.  * - $info_split['upload']: Number of attachments output as "% attachments", %
  29.  *   being the count. Depends on upload.module.
  30.  *
  31.  * Since $info_split is keyed, a direct print of the item is possible.
  32.  * This array does not apply to user searches so it is recommended to check
  33.  * for their existance before printing. The default keys of 'type', 'user' and
  34.  * 'date' always exist for node searches. Modules may provide other data.
  35.  *
  36.  *   <?php if (isset($info_split['comment'])) : ?>
  37.  *     <span class="info-comment">
  38.  *       <?php print $info_split['comment']; ?>
  39.  *     </span>
  40.  *   <?php endif; ?>
  41.  *
  42.  * To check for all available data within $info_split, use the code below.
  43.  *
  44.  *   <?php print '<pre>'. check_plain(print_r($info_split, 1)) .'</pre>'; ?>
  45.  *
  46.  * @see template_preprocess_search_result()
  47.  */
  48. ?>
  49. <?php
  50.         // The code below is a walkaround of the issue that
  51.         // search_excerpt() in search.module fails to create snippet
  52.         //
  53.         // To Do: create alternative of search_excerpt() for multibyte languages
  54.         //
  55.         if(!$snippet || (mb_strlen($snippet) < 20)) {
  56.                 // get node
  57.                 $node = $result['node'];
  58.                 // create digest
  59.                 $digest = $node->teaser_include ? $node->teaser . $node->body : $node->body;
  60.                 // strip HTML tags
  61.                 $digest = strip_tags($digest);
  62.                 // truncate to 200 characters
  63.                 $digest = mb_substr($digest, 0, 200) . '...';
  64.         }
  65.         else {
  66.                 $digest = $snippet;
  67.         }
  68.         // get search keywords
  69.         $keys = search_get_keys();
  70.         // cleanup seach keywords
  71.         if(function_exists(mb_convert_kana)) {
  72.                 $keys = mb_convert_kana($keys, 's'); // zenkaku space to hankaku space
  73.         }
  74.         $keys = preg_replace('/,/', ' ', $keys); // comma to space
  75.         $keys = preg_replace('/\s+/', ' ', $keys); // multiple space to single space
  76.         $keys_array = explode(' ', $keys);
  77.  
  78.         // highlight the search keywords
  79.         foreach($keys_array as $key) {
  80.                 $digest = str_replace($key, "<strong>$key</strong>", $digest);
  81.         }
  82. ?>
  83. <dt class="title">
  84.   <a href="<?php print $url; ?>"><?php print $title; ?></a>
  85. </dt>
  86. <dd>
  87.   <?php if ($snippet) : ?>
  88.     <p class="search-snippet"><?php print $snippet; ?></p>
  89.   <?php endif; ?>
  90.   <?php if ($info) : ?>
  91.   <p class="search-info"><?php print $info; ?></p>
  92.   <?php endif; ?>
  93. </dd>
ちょっと長いですけど前半はコメントだけなので実質はそれほどでもないです。
このファイル「search-result.tpl.php」はDrupal 6.14の標準モジュールであるSearchモジュールのディレクトリの中に含まれているものを自分の使っているテーマのディレクトリにコピーしてきて修正をくわえたものです。このサンプルでは説明文(ダイジェスト)の長さを200文字にしていますが自分の好きな長さにしてください。

以下の添付ファイルはこのsearch-result.tpl.phpをzip圧縮したものです。使われているテーマファイルのディレクトリにコピーし、Searchモジュールを一度無効にしてから有効にしてやる必要があります。

このsearch-result.tpl.phpの最後の部分を自分で手を加えることで、検索結果の表示をカストマイズすることができます。当サイトでもちょっとだけいじっています。

このテンプレートでは検索結果の説明文が「...  ...」になってしまう場合に、無条件でノードの先頭から200文字を切り出しています。ですので、その中に検索キーワードが含まれない可能性があります。
日本語の処理に問題があるsearch_excerpt()関数の代換関数を作成すれば良いのですが時間がなくそこまで手がまわりませんので今のところは応急処置ですませてしまっています。

 

添付サイズ
search-result.tpl_.zip1.5 KB
あなたの評価: なし 平均: 5 (1 vote)