2013-10-19 25 views
4

我正在爲一個網站構建法語MySQL數據庫,這個網站在某些地方將包含重音字符和帽子。所有這些都很完美。str_replace(或preg_replace?)接受和保留重音字符和帽子

現在我設計了一張顯示數據庫內容(完美工作)的表格,並在其上放置了一個搜索欄。用於搜索的SQL查詢按預期工作(使用LIKE,它不區分大小寫,並將重音字符視爲其基本字母,這令人驚訝地正是我想要的)。

這是我的問題:我想直接在表中突出顯示搜索的所有實例。我把它部分地與這方面的工作:

str_ireplace($_POST["search"], 
      '<span class="highlight">' . $_POST["search"] . "</span>", 
      $row['First_Name']); 

但出現這些問題:

  • 它改變了我的表蓋基於搜索輸入
  • 如果用戶忽略重音符號(搜索「 ecole「,同時尋找」école「),搜索不起作用

我一直在尋找過去3小時沒有任何運氣的解決方案。我開始閱讀有關preg_replace()的文章,但似乎無法找到正確的方法,而無需手動爲每個可能的重音字符編寫無盡的代碼。如果我可以模仿SQL Query用「LIKE」做什麼,但是在PHP或其他東西中,那將會很棒。

+0

因此,要總結,你想'somefunction(「fooâccéntbar」,「accent」)=「foo éccént bar」'?這是一個很好的問題,我從來沒有處理過這個問題...... – Wrikken

+0

目前,我只能想到一個帶有正則表達式的'preg_replace_callback',該正則表達式匹配任何在兩側都有字邊界的東西'\ b 。*?\ b',它檢查一個'iconv'到ascii是否會生成您的searchterm,並將其返回爲高亮顯示,如果不是,則按原樣顯示。 – Wrikken

回答

2

您這樣做的方式,您將始終顯示用戶輸入的內容,並且實際上PHP不會與MySQL LIKE進行相同的寬鬆比較。

這是我寫的一個處理這個問題的函數,包括大部分法語重音字符。

function highlight_substring($string, $substring) 
{ 
    if(empty($string) || empty($substring)) return false; 

    $normal = array('à', 'é', 'è', 'ê', 'ë', 'î', 'ï', 'ô', 'ò', 'ö', 'û', 'ü', 'ù', 'ç'); 
    $flat = array('a', 'e', 'e', 'e', 'e', 'i', 'i', 'o', 'o', 'o', 'u', 'u', 'u', 'c'); 

    $str = mb_strtolower($string); 
    $str = str_replace($normal, $flat, $str); 

    $sub = mb_strtolower($substring); 
    $sub = str_replace($normal, $flat, $sub); 

    $pos = mb_strpos($str, $sub); 

    if($pos !== false) 
    { 
    $var = mb_substr($string, 0, $pos).'<span class="highlight">'.mb_substr($string, $pos, mb_strlen($substring)).'</span>'; 
    $var .= mb_substr($string,(bcadd(mb_strlen($substring), $pos))); 
    $string = $var; 
    } 

    return $string; 
} 

隨意調整和改進;)

使用

echo highlight_substring('Allons à l’école !', 'ecole'); // user input 'ecole' 
echo highlight_substring('Allons à l’École !', 'ecole'); // user input 'ecole' 
echo highlight_substring('Allons à l’école !', 'Ecole'); // user input 'Ecole' 

將輸出:

Allons à l’<span class="highlight">école</span> ! 
Allons à l’<span class="highlight">École</span> ! 
Allons à l’<span class="highlight">école</span> ! 
+0

問題。不是OP所期待的:「但是似乎無法找到正確的方式來完成這個任務,而無需手動爲每個可能的重音字符編寫無窮無盡的代碼」 – kero

+1

實際上,您沒有無窮無盡的列表,您只需要將帳戶對於整個Unicode集合;)但是,如果OP只處理法語輸入,那就可以做到這一點。現在,如果你有一個完美的解決方案,請分享,我真的很感興趣。 –

+0

謝謝你的快速回答。即使你的代碼分別處理每個重音字符,而這不是我所尋找的,我可以使用它的一些,但我擔心它不能解決我的帽子問題... – Fierceblood

-1

想想使用正則表達式時忽略重音。類似的東西:

$value = 'É ç école'; 

echo preg_replace("/&([a-z])[a-z]+;/i", "$1", htmlentities($value)); 
1

這裏是PHP 5.3+另一種變體,它有1個問題 - 它實際上消除acutes,也許這將作爲部分解決方案

mb_regex_encoding('utf-8'); 
mb_internal_encoding('utf-8'); 

$row = array('First_Name' => 'some École text with école ecole end of some text '); 

function highlightString($string, $word) 
{ 
    $string = iconv('utf-8', 'ISO-8859-1//IGNORE', Normalizer::normalize($string, Normalizer::FORM_D)); 
    $word = iconv('utf-8', 'ISO-8859-1//IGNORE', Normalizer::normalize($word, Normalizer::FORM_D)); 
    return mb_ereg_replace_callback('('.$word.')', function ($m) { return '<span class=\"highlight\">'.$m[0].'</span>';}, $string, 'msri'); // it is not very secure to use data from POST directly 
} 

echo highlightString($row['First_Name'], 'école') . " <br>\n"; 
echo highlightString($row['First_Name'], 'ecole'). " <br>\n";