2009-09-20 5 views
11

Je suis en train de faire le remplacement de caractères accentués en PHP, mais obtenir des résultats géniaux, je pense être parce que je suis en utilisant une chaîne UTF-8 et str_replace peut ne pas gérer correctement les chaînes multi-octets ..PHP Multi Byte str_replace?

$accents_search  = array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è', 
'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø', 
'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ'); 

$accents_replace = array('a','a','a','a','a','a','a','A','A','A','A','A','e','e', 
'e','e','E','E','E','E','i','i','i','i','I','I','I','I','oe','o','o','o','o','o','o', 
'O','O','O','O','O','u','u','u','U','U','U','c','C','N','n'); 

$str = str_replace($accents_search, $accents_replace, $str); 

résultats Je reçois:

Ørjan Nilsen -> �orjan Nilsen 

Résultat attendu:

Ørjan Nilsen -> Orjan Nilsen 

Edit: J'ai obtenu mon gestionnaire de caractère interne défini sur UTF-8 (selon mb_interna l_encoding()), aussi la valeur de $ str est UTF-8, donc d'après ce que je peux dire, toutes les chaînes impliquées sont UTF-8. Str_replace() détecte-t-il les jeux de caractères et les utilise-t-il correctement?

+0

Vérifiez ma réponse ici: [Correction des caractères en PHP] (http://stackoverflow.com/a/9499771/318380). Cela m'a beaucoup aidé !!! – jazkat

Répondre

5

On dirait que la chaîne n'a pas été remplacée car votre encodage d'entrée et la non-concordance d'encodage de fichier.

+0

Aye, le fichier UTF-8 fonctionne sur cli dans un fichier texte (ne pas sortir au terminal iso) fonctionne. – OIS

+0

Alors, comment puis-je changer mon encodage d'entrée? – Ian

+0

J'ai vérifié mon éditeur de texte, son encodage de fichier est réglé sur UTF-8. – Ian

2

Essayez cette définition de fonction:

if (!function_exists('mb_str_replace')) { 
    function mb_str_replace($search, $replace, $subject) { 
     if (is_array($subject)) { 
      foreach ($subject as $key => $val) { 
       $subject[$key] = mb_str_replace((string)$search, $replace, $subject[$key]); 
      } 
      return $subject; 
     } 
     $pattern = '/(?:'.implode('|', array_map(create_function('$match', 'return preg_quote($match[0], "/");'), (array)$search)).')/u'; 
     if (is_array($search)) { 
      if (is_array($replace)) { 
       $len = min(count($search), count($replace)); 
       $table = array_combine(array_slice($search, 0, $len), array_slice($replace, 0, $len)); 
       $f = create_function('$match', '$table = '.var_export($table, true).'; return array_key_exists($match[0], $table) ? $table[$match[0]] : $match[0];'); 
       $subject = preg_replace_callback($pattern, $f, $subject); 
       return $subject; 
      } 
     } 
     $subject = preg_replace($pattern, (string)$replace, $subject); 
     return $subject; 
    } 
} 
+0

peut-être que je me suis trompé, mais il semble que le modèle correct serait: ''/ ('. Preg_quote (implode ('', (array) $ search), '/').' '/ U'' ?? – Igor

3

Il est possible de supprimer à l'aide diacritiques Unicode normalization form D (NFD) et propriétés de caractère Unicode. NFD convertit quelque chose comme le "ü" tréma de "LA LETTRE MINUSCULE LATINE U DIAERESIS" (qui est une lettre) à "LETTRE MINUSCULE LATINE U" (lettre) et "COMBINER DIAERESIS" (pas une lettre).

header('Content-Type: text/plain; charset=utf-8'); 

$test = implode('', array('á','à','â','ã','ª','ä','å','Á','À','Â','Ã','Ä','é','è', 
'ê','ë','É','È','Ê','Ë','í','ì','î','ï','Í','Ì','Î','Ï','œ','ò','ó','ô','õ','º','ø', 
'Ø','Ó','Ò','Ô','Õ','ú','ù','û','Ú','Ù','Û','ç','Ç','Ñ','ñ')); 

$test = Normalizer::normalize($test, Normalizer::FORM_D); 

// Remove everything that's not a "letter" or a space (e.g. diacritics) 
// (see http://de2.php.net/manual/en/regexp.reference.unicode.php) 
$pattern = '/[^\pL ]/u'; 

echo preg_replace($pattern, '', $test); 

sortie:

aaaaªaaAAAAAeeeeEEEEiiiiIIIIœooooºøØOOOOuuuUUUcCNn 

La classe normaliseur fait partie du PECL intl package. (L'algorithme en lui-même n'est pas très compliqué mais il faut charger beaucoup de mappings de caractères afaik.) J'ai écrit un PHP implementation il y a quelques temps.)

(J'ajoute ceci avec deux mois de retard parce que je pense que c'est une bonne technique

+0

Merci, c'est en fait très utile. Bien que je ne veuille pas vraiment l'utiliser dans ce cas parce qu'il en résulte une perte d'accents. – Ian

+3

Je pensais que se débarrasser des accents était ce que vous essayiez de faire? – mermshaus

16

Selon la documentation php str_replace, la fonction est binaire, ce qui signifie qu'elle peut gérer du texte codé UTF-8 sans aucune perte de données.

+0

Merci, dav. Cela devrait être la bonne réponse, car cela explique pourquoi il y a mb_substr() et mb_strlen() mais pas mb_str_replace(). Les deux premières fonctions utilisent (ou renvoient) des positions de décalage pour les caractères de texte (qui dépend du codage du texte) tandis que str_replace() ne le fait pas. C'est pourquoi str_replace() peut fonctionner avec des données UTF-8 en toute sécurité (ou tout autre encodage Unicode ou généralement avec des données binaires). – StanE