Почему строка "райд" состоит из 8 символов?
Выручайте! :help:
Был сайт на php. Пхп файлы кодировались в Windows-1251, однако в базе данных (MySQL) стояла кодировка UTF-8. При работе с базой приходилось всё время кодировать строки туда-обратно. Решил перекодировать файлы на сервере в UTF-8. На первый взгляд операция прошла удачно, но стоило мне авторизироваться на своём сайте, как я заметил проблему. В одном месте ник выводится вертикально следующим образом: implode('<br>', str_split($halfName)). Так вот в этом месте вместо слова Райд пхп вертикально вывел мне в аккурат 8 неизвестных символов (FF отображает их в виде вопросиков). Входе исследований с помощью FirePHP стало ясно, что длина строк (возвращаемая strlen), состоящих из русских символов, УДВАИВАЕТСЯ :blink: , а при применении к этим строкам любых функция (типа str_split или preg_replace) получается абракадабра. Пожалуйста, помогите решить проблему :( |
Уже 33 просмотра и не одного ответа.
Это такая сложная проблема, такой глупый вопрос или такой длинный пост? |
Глупый и противный вопрос. Глупый, потому что UTF-8 - 8бит, 2 байта на символ в отличие от c1251, где 1 байт. Глюки связаны с этим. Противный потому что никому не охота разбираться где и в чём проблема конкретно у вас.
|
В PHP исходный код представляется в однобайтовой кодировке, и также строки состоят только из символов в однобайтовой кодировке, или байтов.
Каждая буква русского алфавита в UTF-8 представляется двумя байтами, отсюда и данная проблема. Иными словами, strlen показывает количество байтов в строке, и все функции, работающие со строками, работают с отдельными байтами. Я вижу 2 способа решить эту проблему. 1) Отправить строку на клиент как есть, а уже на клиенте с помощью Джаваскрипта расположить буквы вертикально. 2) Воспользоваться тем, что в UTF-8 первый байт последовательности байтов, представляющей один пункт Юникода, является в пределах 0 - 127 или 196 - 255, а остальные байты не являются. Поэтому на PHP можно написать собственную функцию, вставляющую "<br>" между пунктами Юникода, вместо implode. |
Цитата:
|
oneguy,
Это всё конечно прекрасно, но не писать же для каждой строковой операции свою функцию. Не зря я наверно сделал бекап windows1251-сайта. Просто даже не ожидал встретиться с такой проблемой, в Интернете читал статьи, где рекомендуют кодировать скрипты в UTF-8. |
Цитата:
|
Цитата:
Цитата:
|
Цитата:
function str_caller() { $args = func_get_args(); $f = array_shift($args); $r = call_user_func_array($f, str_caller_encode($args)); $r = str_caller_encode(array($r), true); return $r[0]; } function str_caller_encode($args, $b=false) { foreach($args as $k => $v) { if (is_string($v)) { if ($b) $args[$k] = iconv('windows-1251', 'utf-8', $v); else $args[$k] = iconv('utf-8', 'windows-1251', $v); } if (is_array($v)) $args[$k] = str_caller_encode($v, $b); } return $args; } Вопрос, на сколько это безопасно. Вдруг какие-либо php-функции таки умеют работать с UTF-8 и неправильно переварят вызванный таким образом cp1251. Не хочется лишней путаницы. |
И вот ещё, для удобства
function create_utf_str_func($fs) { foreach ($fs as $v) { eval(" if (!function_exists(utf_$v)) { function utf_$v() { \$args = func_get_args(); array_unshift(\$args, '$v'); return call_user_func_array('str_caller', \$args); } } "); } } //например: create_utf_str_func(array('str_split')); utf_str_split('some string с русскими буквами'); Вроде работает. Пока буду применять так. |
Часовой пояс GMT +3, время: 06:13. |