Рядок у PHP - це послідовність байтів, а не символів. strlen() рахує байти. У UTF-8 кожна кирилична літера займає 2 байти, тож «привіт» - 12 байтів.
strlen('привіт'); // 12
mb_strlen('привіт'); // 6
mb_substr('привіт', 0, 3); // 'при'
substr('привіт', 0, 3); // зламаний символ: 'п' і половина 'р'
Правило: для тексту, де можуть бути не лише латинські літери, використовуйте mb_*-функції: mb_strlen, mb_substr, mb_strtoupper, mb_str_split. Байтові функції зріжуть символ посередині, і в результаті з'явиться «�».
Нюанси:
mb_*рахують кодові точки Unicode. Емодзі з модифікатором шкіри чи прапор складаються з кількох точок, і для «видимих символів» потрібенgrapheme_strlen()з розширення intl.strlen()не помилка - він потрібен, коли важливі саме байти: розмір тіла запиту, обмеження колонки в байтах.- У Laravel
Str::length(),Str::limit()уже працюють черезmb_*.