Определение размера строки в PHP: от strlen до mb_strlen
Функции для работы с длиной строки
Какое решение считать наиболее универсальным для подсчёта символов в строке?
Для корректной работы с многобайтовыми кодировками, такими как UTF-8, основной функцией является mb_strlen(). Она возвращает количество символов (код-пойнтов) с учётом указанной кодировки. Это особенно важно при использовании кириллицы, иероглифов или эмодзи.
<?php
$string = 'Привет, мир!';
echo mb_strlen($string, 'UTF-8'); // 12
?>
Php маленькие буквы (преобразование строки в нижний регистр в php)
Почему это самый эффективный способ?
Функция mb_strlen() поддерживается большинством серверов, легко конфигурируется через mb_internal_encoding() и позволяет избежать ошибок, характерных для strlen() в многобайтовой среде. Для однобайтовых кодировок (например, Windows-1251) она также работает корректно.
Типичная проблема:
Если не указать кодировку вторым аргументом, mb_strlen() использует внутреннюю кодировку, заданную директивой mbstring.internal_encoding в php.ini. По умолчанию это может быть не UTF-8, что приведёт к неверному результату. Решение - всегда явно передавать кодировку.
Как определить количество байтов в строке?
Функция strlen() возвращает количество байтов. Для однобайтовых кодировок (Latin-1, Windows-1251) это совпадает с количеством символов, но для UTF-8 каждый символ может занимать от 1 до 4 байтов, поэтому результат будет расходиться с видимой длиной.
<?php
$string = 'Привет, мир!';
echo strlen($string); // 20 (байт)
?>
Character php (символы php)
Ошибка новичков:
Используют strlen() для проверки длины ввода пользователя (например, логина) в UTF-8. Это приводит к неверной валидации - кириллический символ считается за 2 байта, хотя визуально это один символ. Решение - заменить на mb_strlen().
Как подсчитать символы в других многобайтовых кодировках?
Функция iconv_strlen() из расширения iconv также корректно считает символы для UTF-8 и других кодировок. Она может быть полезна, если расширение mbstring не установлено.
<?php
$string = 'Привет, мир!';
echo iconv_strlen($string, 'UTF-8'); // 12
?>
Php new line (символ новой строки в php)
Проблема: некоторые строки в UTF-8 содержат суррогатные пары (эмодзи). iconv_strlen() считает каждый блок графемы как один символ, так как эмодзи обычно кодируются как один символ Unicode. Однако более сложные графемы (например, с модификаторами кожи) требуют специальной обработки.
Как посчитать количество графем (видимых символов) в строке с эмодзи?
Для точного подсчёта видимых символов (графемных кластеров) используется функция grapheme_strlen() из расширения intl. Она правильно обрабатывает комбинированные символы, такие как эмодзи с тоном кожи или флаги.
<?php
$emoji = '??';
echo grapheme_strlen($emoji); // 1 (один графема)
echo mb_strlen($emoji, 'UTF-8'); // 2 (два код-пойнта)
?>
Проблема: расширение intl может быть недоступно на сервере. Встроенная поддержка графем в PHP стандартными средствами отсутствует, поэтому для точного разбора может потребоваться сторонняя библиотека (например, Symfony Polyfill).
Развёрнутые примеры и результаты
Сравнение strlen, mb_strlen, iconv_strlen и grapheme_strlen на разных строках.
<?php
$strings = [
'Hello, world!', // латиница
'Привет, мир!', // кириллица
'你好,世界!', // китайские иероглифы
'?❤️', // эмодзи (огонь и сердце)
'????', // семейная графема (4 код-пойнта)
];
foreach ($strings as $s) {
echo "Строка: " . $s . PHP_EOL;
echo "strlen: " . strlen($s) . " байт" . PHP_EOL;
echo "mb_strlen(UTF-8): " . mb_strlen($s, 'UTF-8') . " символов" . PHP_EOL;
echo "iconv_strlen(UTF-8): " . iconv_strlen($s, 'UTF-8') . " символов" . PHP_EOL;
if (function_exists('grapheme_strlen')) {
echo "grapheme_strlen: " . grapheme_strlen($s) . " графем" . PHP_EOL;
}
echo PHP_EOL;
}
?>
Строка: Hello, world! strlen: 13 байт mb_strlen(UTF-8): 13 символов iconv_strlen(UTF-8): 13 символов grapheme_strlen: 13 графем Строка: Привет, мир! strlen: 20 байт mb_strlen(UTF-8): 12 символов iconv_strlen(UTF-8): 12 символов grapheme_strlen: 12 графем Строка: 你好,世界! strlen: 15 байт mb_strlen(UTF-8): 5 символов iconv_strlen(UTF-8): 5 символов grapheme_strlen: 5 графем Строка: ?❤️ strlen: 6 байт mb_strlen(UTF-8): 3 символов iconv_strlen(UTF-8): 3 символов grapheme_strlen: 2 графем Строка: ???? strlen: 25 байт mb_strlen(UTF-8): 7 символов iconv_strlen(UTF-8): 7 символов grapheme_strlen: 1 графем
Настройка внутренней кодировки для mb_strlen
Чтобы каждый раз не указывать кодировку, можно задать её глобально:
<?php
mb_internal_encoding('UTF-8');
$text = 'Функция mb_strlen';
echo mb_strlen($text); // 18 (теперь можно без второго аргумента)
?>
Определение длины в разных кодировках
<?php
$string = 'Привет';
echo "В UTF-8: " . mb_strlen($string, 'UTF-8') . "\n"; // 6
echo "В UTF-16: " . mb_strlen($string, 'UTF-16') . "\n"; // 6
echo "В Windows-1251: " . mb_strlen($string, 'Windows-1251') . "\n"; // 6 (если символы есть в кодировке)
?>
В UTF-8: 6 В UTF-16: 6 В Windows-1251: 6
Проверка пустой строки и строк только из пробелов
<?php
$empty = '';
$spaces = ' ';
echo "Пустая строка: " . mb_strlen($empty, 'UTF-8') . "\n"; // 0
echo "Строка пробелов: " . mb_strlen($spaces, 'UTF-8') . "\n"; // 3
?>
Использование strlen с бинарными данными
Если нужно узнать размер в байтах для работы с бинарными данными (например, чтение файла), strlen - правильный выбор.
<?php
$binary = pack('H*', 'FFD8FFEE'); // первые байты JPEG
echo strlen($binary); // 4
?>