[RESOLU] Problèmes d'accents avec preg_replace_callback

Eléphant du PHP | 65 Messages

28 févr. 2017, 18:33

Bonjour à tous,
J'ai des problèmes d'accents avec preg_replace_callback et je ne sais pas comment faire:

Code : Tout sélectionner

<?php header('content-type:text/html;charset=utf-8'); setlocale(LC_ALL,'french'); $test = 'Voici des caractères accentués.'; $res = preg_replace_callback('#\b(\w+)\b#',function($cpt){ return mb_strtoupper($cpt[1],'utf-8'); },$test); $autre_res = mb_strtoupper('É','utf-8'); var_dump($res); // Les mots ont des points d'interrogations à la place des accents var_dump($autre_res); // Fonctionne correctement
J'ai compris que c'est preg_replace_callback qui cause ce problème mais je ne sais pas comment le résoudre. Quelqu'un a une idée ?

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 8758 Messages

01 mars 2017, 10:48

salut,

si tu change l'encodage dans la callback tu as moins de soucis, (iso-8859-1 ou iso-8859-15 produise ce que tu veux sauf que le é reste en minuscule).

par contre dans ton cas je vois pas bien pourquoi tu ne fais pas directement mb_strtoupper($test,'utf-8'); qui devrais revenir au même.
sachant que \w ne semble pas comprendre les caractères accentués ([a-zA-Z] et n'oublions pas que c'est fait par des gens qui n'utilisent pas d'accents cela se comprend).

tu peux tester ton masque et ta chaîne la https://regex101.com/r/nN4fE3/30

si tu places un echo / var_dump dans la callback tu verras bien que l'expression régulière donnes plus de mot que tu ne crois ;)

Code : Tout sélectionner

string 'Voici' (length=5) string 'des' (length=3) string 'caract�' (length=7) string 'res' (length=3) string 'accentu�' (length=8) string 's' (length=1)
donc sans info sur le contexte je te dirais d'utiliser mb_strtoupper($test,'utf-8'); ce sera de toute façon plus efficace.

@+
Il en faut peu pour être heureux ......

Eléphant du PHP | 65 Messages

01 mars 2017, 12:26

Salut,
C'est juste une expérimentation faut pas chercher de logique la dedans.
Sinon, c'est normal que la regex donne tous ces résultats puisque les accents ne sont pas pris en compte par preg_replace_callback, donc pour lui, l'accent grave n'est pas considéré comme un mot, donc il capture.
A force de persévérance j'ai trouvé, il suffit d'activer le modifier "u" pour activer le multibytes:

Code : Tout sélectionner

$test = 'Voici des caractères accentués.'; $res = preg_replace_callback('#\b(\w+)\b#u',function($cpt){ return mb_strtoupper($cpt[1],'utf-8'); },$test); // VOICI DES CARACTÈRES ACCENTUÉS. preg_match_all('#\b(?|\w+)\b#u',$test,$out3); var_dump($out3); /* Et là comme tu peux le constater il n'y a que 4 captures: array (size=1) 0 => array (size=4) 0 => string 'Voici' (length=5) 1 => string 'des' (length=3) 2 => string 'caractères' (length=11) 3 => string 'accentués' (length=10) */