2013-05-11 8 views
16

Sto usando una tabella mysql di charset utf8 in un server MySQL 5.1, che non supporta la codifica utf8mb4 nelle tabelle. Quando si inseriscono caratteri utf8 codificati a 4 byte come "","","","","","唧","". La tabella mostrerà un errore o salterà i seguenti testi.È possibile che php rilevi i caratteri utf8 codificati a 4 byte?

Come posso rilevare a livello di codice utf8 codificati a 4 byte in PHP e sostituirli?

+0

Abbastanza semplice: dividere una stringa da personaggi (molti modi per farlo) e verificare se 'strlen ($ char) == 4'. Non sono sicuro che questo sia davvero il modo corretto per rilevare i caratteri che MySQL non può gestire, in quanto il punto di codice potrebbe essere più preciso. – deceze

+0

Hai controllato l'estensione [multibyte] (http://php.net/mbstring)? Inoltre, assicurati di leggere [sempre i commenti] (http://dk1.php.net/manual/en/function.mb-internal-encoding.php#66568). –

+0

@deceze Questo è un approccio. Vado per quello se non ci sono altri modi eleganti. –

risposta

13

La seguente espressione regolare sostituirà a 4 byte caratteri UTF-8:

function replace4byte($string, $replacement = '') { 
    return preg_replace('%(?: 
      \xF0[\x90-\xBF][\x80-\xBF]{2}  # planes 1-3 
     | [\xF1-\xF3][\x80-\xBF]{3}   # planes 4-15 
     | \xF4[\x80-\x8F][\x80-\xBF]{2}  # plane 16 
    )%xs', $replacement, $string);  
} 

var_dump(replace4byte('d'), replace4byte('dd')); 

Questo non si basa sul modificatore /u, quindi non dovrebbe essere necessario preoccuparsi di UTF-8 per PCRE essere compilato in. Tuttavia, se si dispone di tale supporto, l'inganno preg_replace_callback è più ordinato.

(Regex adattato da Ensuring valid utf-8 in PHP)

13

Questo dovrebbe funzionare:

if (max(array_map('ord', str_split($string))) >= 240) 

punti Il razionale è che il codice fino al U + FFFF sono codificati come tre byte della forma 1110xxxx 10xxxxxx 10xxxxxx. I punti di codice più alti hanno il formato 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, ad esempio il byte più alto ha un valore di 240 o superiore. Se nella stringa sono presenti tali byte, è un indicatore per una sequenza di 4 byte.

Se si desidera rimuovere caratteri, questo farà:

preg_replace_callback('/./u', function (array $match) { 
    return strlen($match[0]) >= 4 ? null : $match[0]; 
}, $string) 

Anche se ci può essere un modo più elegante espressione regolare di esprimere direttamente alti Codepoints.

+0

Grazie per il rilevamento ma puoi finirlo anche con un esempio di sostituzione? $ a = "omg, non posso inserire nel mio tavolo, blahblahblah"; // target $ a == "omg, non posso inserire MYTEXT nel mio tavolo, blahblahblah"; –

Problemi correlati