Проблемы с поиском по кириллице

Mesnyankin

Новичок
Проблемы с поиском по кириллице

Здравствуйте!

Проблема следующего содержания. Делаю интернет магазин www.yougoods.ru на движке Sapid CMF. В форме поиска если запрос вводить на латыне результат выводит. Если на русском, то результа не кокого. К примеру если запрос "новости" на выходе
получаю сообщение "Результаты по запросу - %D0%BD%D0%BE%D0%B2%D0%BE%D1%81%D1%82%D0%B8" и естественно ни чего не находит. Видемо метод Get для передачи запроса преобразует кириллицу в UTF-16. Как решить эту проблему? База данных в utf8_general_ci сравнение то же. Вот код:

get_search.app.php
-----------------------------

<?
function getSearchMatch($keywords) {
$keywords = explode(' ', trim($keywords));
for ($i = 0, $length = sizeof($keywords); $i < $length; ++ $i) {
if (strlen($keywords[$i]) > 2) $keywords[$i] .= '*';
}
$keywords = implode(' ', $keywords);
return "MATCH (B.data) AGAINST('{$keywords}' IN BOOLEAN MODE) ";
}
/**
* Get document/record backup list
*
* @param array system
* @param array system
* @return array results
*/
function get_search($params=array(), $ddc_params=array(), &$ddc_parents) {
global $db;
$SearchMatch = getSearchMatch($params["keywords"]);
$sql = "SELECT {$SearchMatch} as relev, A.url, A.name, UNIX_TIMESTAMP(A.cdate) as cdate_uts, B.qc, B.data FROM ".DOCSTRUCTTABLE." A, ".DOCDATATABLE." B
WHERE {$SearchMatch} >0 AND
A.doc_id = B.struct_id AND
A.site_id = ".SITEID." AND A.everyone='7' GROUP by B.struct_id ORDER by relev DESC";
$data = $db->all($sql);
if($data) {
foreach ($data as $index=> $line) {
$data[$index]["href"] = HTTP_PATH.(preg_replace("/^\//", "", $line["url"]));
}
}
$sql = "SELECT {$SearchMatch} as relev, C.url, A.rec_id, A.name, UNIX_TIMESTAMP(A.cdate) as cdate_uts, B.qc, B.data FROM ".RECSTRUCTTABLE." A, ".RECDATATABLE." B, ".DOCSTRUCTTABLE." C
WHERE {$SearchMatch} >0 AND
C.doc_id = A.document_id AND
A.rec_id = B.struct_id AND
A.site_id = ".SITEID." AND A.everyone='7' GROUP by B.struct_id ORDER by relev DESC";
$rec_data = $db->all($sql);
if($rec_data) {
foreach ($rec_data as $index=> $line) {
$rec_data[$index]["href"] = $line["url"].format2recordid($line["rec_id"])."/";
}
}
$data = array_merge($data, $rec_data);
if($data) {
foreach ($data as $index=> $line) {
$data[$index]["counter"] = $index+1;
$data[$index]["data"] = mb__substr($data[$index]["data"], 1, 300)."...";
}
}
return $data;
}
?>

-~{}~ 30.09.09 16:47:

searchform.tpl - шаблон формы
-------------------------
<form action="/search/" method="GET"> /*вызывает шаблон search.tpl
<input class="text" type="text" name="keywords" />
<input class="botton_search" type="image" src="/views/delivery/img/search.gif" title="Искать" value="Look for" />
</form>
<a href="#">Расширенный поиск</a>
<script language="JavaScript" type="text/javascript">
<!--
var counter = 0
//-->
</script>

-~{}~ 30.09.09 16:48:

search.tpl - шаблон страницы поиска
---------------
В этом файле подключается сценарий ddc - search.xml
...
<sapi:param name="menu">get_tree()</sapi:param>
<sapi:param name="content">
<div id="PageContent">
<sapi:apply name="ddc.search.value" />
</div>
</sapi:param>
...

-~{}~ 30.09.09 16:51:

search.xml - сценарий ddc, так же содержит форму поиска
-----------------
...
<sapi:for-each select="get_search()" name="enum" title="Get channel">
<sapi:params>
<sapi:param name="keywords">&_get_keywords.value;</sapi:param>
<sapi:code>
<div id="search_title">
<form action="/search/" method="GET">
<input class="stext" type="text" name="keywords" />
<input class="botton_search" type="image" src="/views/delivery/img/search.gif" title="Искать" value="Look for" />
</form>
<script language="JavaScript" type="text/javascript">
<!--
var counter = 0
//-->
</script></br>
Результаты по запросу - &_get_keywords.value; </br>
</div>
</sapi:code>
</sapi:params>
<sapi:ifempty>Your search - &_get_keywords.value; - did not match any documents. </sapi:ifempty>
<sapi:fallback>CMS-application error</sapi:fallback>
<sapi:choose>
<sapi:when exp="1">
<sapi:code>
<div id="search_output">
<label class="java">
<script language="JavaScript" type="text/javascript">
<!--
add_one()
function add_one()
{ counter = counter + 1 }
document.write(counter + ". ")
//-->
</script>
</label>
<a href="&this.this.href.value;">&this.this.name.value;</a></br></div>
<div id="search_outtext">&this.this.data.value;</br></br>
<a class="slink" href="&this.this.href.value;"><label>http://www.yougoods.ru&this.this.href.value;</label></a></div>
</sapi:code>
...
Если у кого какие мысли есть помогите. Работа встала. На форуме разрабодчиков CMS похожей ситуации не нашел. Зарание спасибо.
 

dimagolov

Новичок
разберись какая кодировка страницы отдается в заголовке для начала
 

Mesnyankin

Новичок
Автор оригинала: dimagolov
разберись какая кодировка страницы отдается в заголовке для начала
У меня для всех страниц хедер один (heder.tpl). В нем charset=utf-8. Если вы это имели ввиду. Единственно в xml не была указана кодировка. Исправил прописав encoding="UTF-8" Вообщем в php я понимаю не много только благодаря знанию языка С++ мне что-то удается разобрать. А сейчас труба. Намекните хотя бы куда копать?
 

dimagolov

Новичок
копать в заголовки, которые отдает web-сервер.
смотри для начала в браузере каким-нибудь просмотрщиком заголовков, так как то, что на писано в html-е игнорируется если есть кодировка в заголовке пакета.
 

Mesnyankin

Новичок
Понял. Попробую отследить.

-~{}~ 02.10.09 18:09:

Проблему решил частично. Нашел такую вот функцию:
<?php
function unicodeUrlDecode($url, $encoding = "")
{
if ($encoding == '')
{
if (isset($_SERVER['HTTP_ACCEPT_CHARSET']))
{
preg_match('/^\s*([-\w]+?)([,;\s]|$)/', $_SERVER['HTTP_ACCEPT_CHARSET'], $a);
$encoding = strtoupper($a[1]);
}
else
$encoding = 'CP1251'; // default
}

preg_match_all('/%u([[:xdigit:]]{4})/', $url, $a);
foreach ($a[1] as $unicode)
{
$num = hexdec($unicode);
$str = '';

// UTF-16(32) number to UTF-8 string
if ($num < 0x80)
$str = chr($num);
else if ($num < 0x800)
$str = chr(0xc0 | (($num & 0x7c0) >> 6)) .
chr(0x80 | ($num & 0x3f));
else if ($num < 0x10000)
$str = chr(0xe0 | (($num & 0xf000) >> 12)) .
chr(0x80 | (($num & 0xfc0) >> 6)) .
chr(0x80 | ($num & 0x3f));
else
$str = chr(0xf0 | (($num & 0x1c0000) >> 18)) .
chr(0x80 | (($num & 0x3f000) >> 12)) .
chr(0x80 | (($num & 0xfc0) >> 6)) .
chr(0x80 | ($num & 0x3f));

$str = iconv("UTF-8", "$encoding//IGNORE", $str);
$url = str_replace('%u'.$unicode, $str, $url);
}

return urldecode($url);
}
?>

-~{}~ 02.10.09 18:17:

$encoding = 'CP1251'; изменил на UTF-8

и в файле get_search.app.php её вызвал

function get_search($params=array(), $ddc_params=array(), &$ddc_parents) {
global $db;
$params["keywords"]=unicodeUrlDecode($params["keywords"], $encoding = 'UTF-8');
...

Теперь результат поиска на кириллице выводит и то хорошо :), но слова из формы отображает все так же в UTF-16 (Результаты по запросу - BE%D1%81%D1%82%D0%B8...)

-~{}~ 06.10.09 15:58:

Все работает. Не стал парица
сделал так:
$result='%D0%A0%D0%B5%D0%B7%D1%83%D0%BB%D1%8C%D1%82%D0%B0%D1%82%D1%8B+%D0%BF%D0%BE+%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D1%83 - ';
$result=unicodeUrlDecode($result, $encoding = 'UTF-8');
$params["keywords"]=unicodeUrlDecode($params["keywords"], $encoding = 'UTF-8');
echo '<div class="search_keywords">'.$result.$params["keywords"];
echo '</div>';

Если у кого возникнет проблема с кириллицей функция unicodeUrlDecode перекодирует UTF-16 в UTF-8.

dimagolov ты прав, кодировка в заголовке пакета у меня точно где-то меняется, но отследить не смог. Видемо в настройках сервера надо что-то менять. Но доступа у меня нет.Благо нашел решение.
 
Сверху