substr() – как може да се използва с кирилица в UTF-8 encoding

Тази сутрин се сблъсках с интересен проблем, занимавайки се с една мини тикет система за единия от сайтовете ми (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, но въпросния модул  го нямам зареден на тази машина…

This entry was posted in IT and tagged , , , . Bookmark the permalink.

6 Responses to substr() – как може да се използва с кирилица в UTF-8 encoding

  1. Един въпрос, на който предполагам, че знам отговора ама … 🙂

    А дащо не iconv_substr? 😉

  2. JaG says:

    Всъщност iconv_substr наистина е още по-добро решение. Като му се зададе кодировка си бачка екстра на utf-8. Не съм намерил въпросната функция като търсих решение на проблема. Мерси!

  3. Хъм … Преди да попитам забелязах още нещо. Тествах с
    $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 в другия.

    Би ли пробвал как е при теб?

  4. JaG says:

    php5-cli 5.2.4 на ubuntu 8.04 – 2x2Ghz+2GB RAM

    iconv_substr – 13,5-14s
    iconv+substr+iconv – 9,5-10s

    МНОГО странно!?

  5. Ах, онова $mytext не е $mytext 🙂 Но пак има разлика.

    И на мен ми се струва доста странно – в по-бързия случай имаме две “викания” на функции в повече. А освен това нормалната логика е, че когато всичко е описано в една функция има вероятност кода (на C) да е по-оптимизиран.

    Да видим какво ще каже някой гуру 🙂

  6. JaG says:

    Aз при моя тест $mytext го заместих с ‘Кирилица’ и това беше резултата ми… И моята логика беше такава, че трябва да е по-оптимизирано ако се използва само 1 php функция вместо 3, но резултата не показва това.

Leave a Reply

Your email address will not be published. Required fields are marked *