Тази сутрин се сблъсках с интересен проблем, занимавайки се с една мини тикет система за единия от сайтовете ми (brutali.com). PHP функцията substr() не работи коректно с UTF-8 енкодинг, защото при него всеки символ е по 2 байта. Ето пример:
substr(‘Тест текст’, 0, 7);
Използваната функция ще върне: Тес?
При използването сме указали да ни покаже първите 7 символа в задения текст, а за функцията това значи първите 7 байта. В UTF-8 всеки символ като е по 2 байта показва само първите 3 букви, а от третата показва половината или по-точно нищо :). Този проблем го има само с кирилицата, с латиница и числа проблем няма. Ето и моето решение на проблема, след като изчетох няколко материала за фиксване като този и този, но нещо не ми помогнаха и се позамислих… семпло и работещо 100%:
Алгоритъм на действията:
1. Обръщаме стринга в CP1251
2. Режем каквото ни трябва от текста със substr()
3. Обръщаме изходящия текст в UTF-8 и го ползваме за каквото ни трябва
<?php
$mytext = “Кирилица”;
echo iconv(‘cp1251’, ‘utf-8’, substr(iconv(‘utf-8’, ‘cp1251’, $mytext), 0, 5));
?>
Въпросния код ще покаже текста: Кирил
Забележка: Гурутата да не ме нападнат, че не чета php.net и не знам какво е mbstring, при който функцията е mb_substr, но въпросния модул го нямам зареден на тази машина…
Един въпрос, на който предполагам, че знам отговора ама … 🙂
А дащо не iconv_substr? 😉
Всъщност iconv_substr наистина е още по-добро решение. Като му се зададе кодировка си бачка екстра на utf-8. Не съм намерил въпросната функция като търсих решение на проблема. Мерси!
Хъм … Преди да попитам забелязах още нещо. Тествах с
$s=”;
for($i=-1000000;$i<1000000;$i++)
$s=iconv_substr(“Кирилица”,0,5,’utf8′);
и съответно с
$s=iconv(‘cp1251’, ‘utf-8’, substr(iconv(‘utf-8’, ‘cp1251’, $mytext), 0, 5));
При мен (php-cli 5.2.6 на Ubuntu 9.04) iconv_substr работеше забележимо по-бавно. Например 18-18,8 секунди в единия случай и 15-15,8 в другия.
Би ли пробвал как е при теб?
php5-cli 5.2.4 на ubuntu 8.04 – 2x2Ghz+2GB RAM
iconv_substr – 13,5-14s
iconv+substr+iconv – 9,5-10s
МНОГО странно!?
Ах, онова $mytext не е $mytext 🙂 Но пак има разлика.
И на мен ми се струва доста странно – в по-бързия случай имаме две “викания” на функции в повече. А освен това нормалната логика е, че когато всичко е описано в една функция има вероятност кода (на C) да е по-оптимизиран.
Да видим какво ще каже някой гуру 🙂
Aз при моя тест $mytext го заместих с ‘Кирилица’ и това беше резултата ми… И моята логика беше такава, че трябва да е по-оптимизирано ако се използва само 1 php функция вместо 3, но резултата не показва това.