Чтобы избежать «символов монстров», я выбираю форму Unicode NCR для хранения неанглийских символов в базе данных (MySQL). Тем не менее, плагин PDF, который я использую (FPDF), не принимает форму Unicode NCR как правильный формат; он отображает данные непосредственно так:
這個一個例子
но я хочу, чтобы он отображался следующим образом:
這個 一個 例子
Есть ли способ конвертировать форму Unicode NCR в ее первоначальную форму?
ps смысл предложения – это «это пример» на традиционном китайском языке.
ps Я знаю, что форма NCR оставляет место для хранения, но это самый безопасный способ хранения неанглийских символов. Поправьте меня, если я ошибаюсь. Благодарю.
Существует более простое решение, использующее расширение PHP mbstring.
// convert any Decimal NCRs to Unicode characters $string = "這個一個例子"; $output = preg_replace_callback( '/(&#[0-9]+;)/u', function($m){ return utf8_entity_decode($m[1]); }, $string ); echo $output; // 這個一個例子//callback function for the regex function utf8_entity_decode($entity){ $convmap = array(0x0, 0x10000, 0, 0xfffff); return mb_decode_numericentity($entity, $convmap, 'UTF-8'); }
Функция «utf8_entity_decode» принадлежит PHP.net (Andrew Simpson): http://php.net/manual/ru/function.mb-decode-numericentity.php#48085 . Я немного изменил код, чтобы избежать устаревшего 'e'-модификатора в Regex.
Решение очень сложно.
Есть 3 части решения: Часть 1: Установка FPDF Chinese Plug-in Часть 2: Преобразование формата NCR в UTF-8 Часть 3: Преобразование формата UTF-8 в BIG5 (или любая целевая кодировка)
Я выбрал китайский плагин FPDF: http://dev.xoofoo.org/modules/content/d1/d6e/a00073.html Он используется для отображения китайских иероглифов в FPDF и для получения всех необходимых китайских шрифтов. Чтобы установить этот плагин, просто включите его в PHP. (но для моего случая я использую другой плагин с именем CellPDF, который сбой с этим китайским подключаемым модулем, поэтому мне нужно объединить коды и разрешить конфликты)
Чтобы преобразовать формат NCR в UTF-8, я использую следующие коды:
function html_entity_decode_utf8($string) { static $trans_tbl; // replace numeric entities $string = preg_replace('~&#x([0-9a-f]+);~ei', 'code2utf(hexdec("\\1"))', $string); $string = preg_replace('~&#([0-9]+);~e', 'code2utf(\\1)', $string); // replace literal entities if (!isset($trans_tbl)) { $trans_tbl = array(); foreach (get_html_translation_table(HTML_ENTITIES) as $val=>$key) $trans_tbl[$key] = utf8_encode($val); } return strtr($string, $trans_tbl); } function code2utf($num) { if ($num < 128) return chr($num); if ($num < 2048) return chr(($num >> 6) + 192) . chr(($num & 63) + 128); if ($num < 65536) return chr(($num >> 12) + 224) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128); if ($num < 2097152) return chr(($num >> 18) + 240) . chr((($num >> 12) & 63) + 128) . chr((($num >> 6) & 63) + 128) . chr(($num & 63) + 128); return ''; }
который написан laurynas butkus на php.net (ссылка: http://www.php.net/manual/en/function.html-entity-decode.php ). Хотя этот фрагмент кода преобразует формат NCR в «персонажи-монстры» «Я знаю, что это хорошее начало.
После того, как я углубился в php.net, я нашел приятную функцию: iconv, чтобы преобразовать кодировку. Поэтому я завершаю вышеуказанные коды с помощью следующей функции:
function ncr_decode($string, $target_encoding='BIG5') { return iconv('UTF-8', 'BIG5', html_entity_decode_utf8($string)); }
Поэтому, если я хочу преобразовать предыдущую строку строк NCR, мне нужно только запустить эту функцию:
ncr_decode("這個一個例子");
ps по умолчанию, я задал целевую кодировку BIG5.
Это оно!
Взгляните на html_entity_decode
.
PS: Лучше всего использовать UTF-8 на всем протяжении. Поиск по SO для вопросов, касающихся PHP, MySQL и UTF-8, есть несколько, которые перечисляют возможные ошибки.