PHP: полный мануал с примерами, функциями и ООП
Практический мануал PHP: от переменных и читаемого кода до безопасных форм, интеграций, базы данных и ООП на примере магазина. Учебный маршрут, поиск функций, подробные примеры, разбор ошибок и исходники для скачивания.

Дерево руководства
Глава 78 · Сначала текст, затем импорт и протоколы
Многобайтовые строки: полный справочник mbstring
Длина и поиск Unicode, границы байтов, старые кодировки, японский текст, регулярные выражения, HTTP и почта — от понятной первой строки до точных контрактов функций.
Посчитать название товара, а не размер его байтов
Одна строка «Мир», два правильных результата
Кодировка UTF-8 объясняет, как байты объединяются в знаки. Выбираем измерение под правило формы или протокола.
- strlen → 6 байтов
Для размера файла и байтового бюджета считаются все шесть единиц хранения.
- D0 9C
Два байта для буквы М.
- D0 B8
Два байта для буквы и.
- D1 80
Два байта для буквы р.
- mb_strlen UTF-8 → 3 кодовые точки
Декодер видит три знака Unicode. Исходная строка не меняется.
- М → U+041C
Одна кодовая точка, индекс 0.
- и → U+0438
Одна кодовая точка, индекс 1.
- р → U+0440
Одна кодовая точка, индекс 2.
В этом слове каждая буква — одна кодовая точка. Составной emoji или буква с отдельным акцентом могут занимать несколько точек: для видимых знаков нужна графемная модель.
В каталоге разрешено короткое название. «Мир» состоит из трёх букв, но в UTF-8 занимает шесть байтов. Сначала получим полезный результат одной функцией. Затем научимся выбирать единицу длины и не портить данные при импорте.
- Переменная $title хранит байты текста Мир
- UTF-8 задаёт, какие байты составляют одну кодовую точку
- mb_strlen($title, 'UTF-8') возвращает число 3
- echo печатает результат; исходный $title не меняется
$title — имя переменной; = сохраняет значение справа; кавычки ограничивают текст. Имя функции перед круглыми скобками указывает действие. В скобках через запятую передаются текст и название его кодировки. Функция возвращает число; echo выводит его. Точка с запятой завершает инструкцию.
<?php
declare(strict_types=1);
$title = 'Мир';
echo mb_strlen($title, 'UTF-8'), "\n";
echo strlen($title), "\n";
Ожидаемый результат
3
6
Сохраните файл в UTF-8 и выполните php example.php. mb_strlen — функция расширения mbstring; strlen работает с байтами. Обе полезны, но отвечают на разные вопросы. Если расширение не установлено, сначала откройте следующий раздел.
Предпосылки: переменная и присваивание, вызов и возвращаемое значение. Не начинайте с регулярных выражений: для длины готовая функция проще.
Байт, кодовая точка, графема и ширина — четыре шкалы
Байт состоит из восьми битов и имеет 256 возможных значений. Для всех языков этого недостаточно: многобайтовая кодировка использует несколько байтов на некоторые знаки. В диагностике 0xFF — шестнадцатеричная запись одного байта, U+20AC — номер знака евро в Unicode; это разные уровни описания.
| Что считаем | Пример и задача | Инструмент |
|---|---|---|
| Байты | Размер файла, протокольный лимит поля, бинарные данные | strlen; mb_strcut режет байтовый бюджет по границам символов |
| Кодовые точки Unicode | В UTF-8 А — одна, e + объединяющий акцент — две | mb_strlen, mb_substr, mb_str_split |
| Графемные кластеры | Один воспринимаемый знак может содержать несколько кодовых точек | grapheme_strlen / grapheme_substr из intl; отдельная зависимость |
| Условная восточноазиатская ширина | Узкие знаки 1, широкие 2; удобно для согласованного текстового отчёта | mb_strwidth, mb_strimwidth; не измерение пикселей |
<?php
declare(strict_types=1);
$composed = "é";
$combined = "e\u{0301}";
echo strlen($composed), '/', mb_strlen($composed, 'UTF-8'), "\n";
echo strlen($combined), '/', mb_strlen($combined, 'UTF-8'), "\n";
echo mb_strwidth('A東', 'UTF-8'), "\n";
Ожидаемый результат
2/1
3/2
3
Запись \u{0301} в двойных кавычках добавляет объединяющий акцент. mbstring не нормализует эти строки в одну форму. Для Unicode-нормализации нужен Normalizer из intl; визуальная похожесть сама по себе не делает логины одинаковыми.
Составной emoji может содержать соединители, модификаторы и несколько картинок. Ни mb_strlen, ни mb_strwidth не обещает посчитать то, что человек увидит одним знаком. Правило поля нужно сформулировать явно: байты протокола, кодовые точки или графемы. Сначала проверяют корректность кодировки, затем применяют выбранное ограничение. SQL-коллация и JavaScript length могут использовать другие правила: согласуйте контракт формы и сервера.
Подключить расширение и проверить именно нужный PHP
mbstring — расширение PHP, а не Composer-пакет и не переключатель UTF-8 в редакторе. Оно не обязано входить в минимальную сборку. В консоли php --ini показывает конфигурацию CLI, php --ri mbstring — расширение. У сайта другой SAPI и иногда другая версия/INI; подтверждать загрузку нужно в обоих окружениях, не публикуя полный phpinfo с путями и секретами.
<?php
declare(strict_types=1);
echo extension_loaded('mbstring') ? 'mbstring: yes' : 'mbstring: no';
echo "\n";
echo function_exists('mb_ereg') ? 'mbregex: yes' : 'mbregex: no';
Ожидаемый результат
mbstring: yes
mbregex: yesВ проверенной сборке обе возможности доступны. На другом компьютере no — причина установить/включить подходящий модуль, а не включать автоматическое преобразование HTTP.
В Windows используют расширение из совместимого комплекта PHP: архитектура, TS/NTS и версия должны совпадать; проверьте extension_dir и загрузку mbstring в фактически используемом php.ini. В Linux/macOS способ установки зависит от дистрибутива или менеджера пакетов. После изменения конфигурации веб-процессы перезапускают штатным способом; новая CLI-команда прочитает INI заново. Как найти действующую конфигурацию.
При сборке из исходников включают --enable-mbstring. libmbfl поставляется с PHP; возможность внешней библиотеки --with-libmbfl относилась к версиям до 7.3. Regex-часть можно исключить --disable-mbregex; с PHP 7.4 Oniguruma ищется через pkg-config, до этого библиотека поставлялась в исходниках и существовал --with-onig. Опция --disable-mbregex-backtrack отключает проверку обратного поиска и не является ускорением, которое стоит бездумно включать. Наличие mb_strlen ещё не доказывает наличие mb_ereg.
Как читать сигнатуры и не прятать ошибки
string — строка байтов; int — целое; bool — true/false; array — массив. ?string разрешает строку или null; string|false — два возможных результата. = null задаёт поведение при пропущенном аргументе. Амперсанд & у параметра означает изменение переданной переменной: для mb_parse_str и mb_convert_variables это принципиально. В примерах эти правила раскрываются на маленьких вызовах до массивов и callback.
В большинстве текстовых функций encoding = null означает текущую внутреннюю кодировку. mb_internal_encoding не преобразует уже существующие байты, не меняет кодировку исходного файла, базы или regex. Regex использует отдельное mb_regex_encoding. Для точного контракта передавайте известное UTF-8 явно; для старого файла сначала проверьте его заявленную кодировку и преобразуйте один раз на границе.
На современном PHP неизвестное имя кодировки обычно вызывает ValueError; неверный тип при strict_types=1 — TypeError; неверное число аргументов — ArgumentCountError. В слабом режиме скаляры иногда преобразуются; null для ненулевого встроенного параметра deprecated с 8.1. Не ловите всё ради пустой строки: неверная конфигурация не равна пустому полю. Ошибочная последовательность байтов не всегда вызывает исключение: проверка, подстановка и конкретная функция имеют разные контракты.
Настройки mb_* действуют в текущем запросе/процессе. В долгоживущем worker их может увидеть следующая задача; временное изменение оборачивают try/finally и восстанавливают. Это не передача настроек между отдельными HTTP-запросами. В книге примеры исполняются отдельно; отправка почты и реальные HTTP-заголовки отмечены как контекстные, не как подтверждённая доставка.
Какие настройки меняют смысл текста
Рабочая исходная договорённость для нового сайта: PHP-файлы и входной JSON в UTF-8, кодировка подключения БД задана явно, ответы помечены правильным Content-Type. Автоматическое перекодирование всего входа оставляют выключенным. Изменить название кодировки без преобразования байтов — всё равно что сменить подпись на коробке: содержимое останется прежним.
| INI: значение по документации | Где меняется | Назначение и граница |
|---|---|---|
| mbstring.language = neutral | INI_ALL | Языковой профиль, прежде всего для почты; не переводит текст и не задаёт локаль регистровых операций |
| mbstring.detect_order = NULL | INI_ALL | Кандидаты определения; null использует профиль. Порядок не гарантирует выбор первого допустимого с PHP 8.1 |
| mbstring.http_input = pass | INI_ALL; deprecated | Устаревшая настройка входной кодировки; для нового кода явный договорённый вход |
| mbstring.http_output = pass | INI_ALL; deprecated | Устаревшая настройка выхода; сама не равна установке callback буфера |
| mbstring.internal_encoding = NULL | INI_ALL; deprecated | Для нового INI оставить пустой и использовать default_charset; отдельная функция mb_internal_encoding не объявлена устаревшей |
| mbstring.substitute_character = NULL | INI_ALL | Подстановка при недопустимых/непредставимых символах; смотреть mb_substitute_character |
| mbstring.func_overload = 0 | Исторически INI_SYSTEM | Deprecated 7.2, удалена в 8.0; не включать в современную конфигурацию |
| mbstring.encoding_translation = 0 | INI_PERDIR | Преобразование входных данных до выполнения PHP-кода; ini_set внутри обработчика уже не перепарсит запрос |
| mbstring.http_output_conv_mimetypes = ^(text/|application/xhtml\+xml) | INI_ALL | Какие Content-Type подходят для преобразования выходного буфера |
| mbstring.strict_detection = 0 | INI_ALL | Поведение при отсутствии допустимого кандидата; явный true в mb_detect_encoding нагляднее зависимости от INI |
| mbstring.regex_stack_limit = 100000 | INI_ALL; с 7.3.5 | Предел стека regex; не заменяет безопасную структуру шаблона |
| mbstring.regex_retry_limit = 1000000 | INI_ALL; с 7.4 | Предел повторов regex; требует Oniguruma ≥ 6.8.0 |
INI_ALL допускает изменение во время исполнения там, где хостинг не ограничил настройку. INI_PERDIR требует конфигурации до запроса: способ зависит от SAPI (.user.ini для соответствующего CGI/FastCGI, php_value в .htaccess только при подходящем модуле Apache). INI_SYSTEM меняется на серверном уровне. Границы php.ini и SAPI. Старые примеры с EUC-JP/SJIS в php.ini описывают целиком согласованный legacy-сайт; переносить отдельные строчки в UTF-8-приложение опасно. Языковой профиль исторически влияет на выбор внутренних настроек, поэтому порядок старых INI-директив также имел значение.
<?php
declare(strict_types=1);
$previous = mb_internal_encoding();
try {
mb_internal_encoding('UTF-8');
echo mb_strlen('Заказ'), "\n";
} finally {
mb_internal_encoding($previous);
}
echo mb_internal_encoding() === $previous ? 'restored' : 'changed';
Ожидаемый результат
5
restoredtry выполняет работу, finally выполняется и при исключении. Для одной операции mb_strlen(..., UTF-8) ещё проще: не приходится менять общее состояние.
Кодировка задаёт соответствие байтов и знаков
- Файл пришёл вместе с договорённостью Windows-1251
- Сначала ограничить размер и проверить допустимые байты
- Преобразовать Windows-1251 → UTF-8 один раз
- Работать с UTF-8; хранить исходник отдельно, если нужен аудит импорта
Unicode присваивает знакам кодовые точки U+…; UTF-8, UTF-16 и UTF-32 — способы записать их байтами. Современные Unicode scalar values находятся до U+10FFFF, исключая диапазон суррогатов U+D800–U+DFFF. Историческое описание UCS-4 с 31-битным пространством не разрешает создавать такие «символы Unicode» в современном API. В UTF-16 знак за пределами BMP занимает пару кодовых единиц; UCS-2 такой пары не описывает. BE/LE — порядок байтов многобайтовой единицы.
| Семейство | Как трактовать |
|---|---|
| UTF-8 | Переменная длина; ASCII-совместим. Рекомендуемый договор для нового веб-приложения |
| UTF-16 / UTF-32; UCS-2 / UCS-4 | Формы без BE/LE могут учитывать начальный BOM при преобразовании; с BE/LE порядок указан явно. Не вычислять число Unicode-знаков простым делением размера UTF-16 на два |
| ASCII / ISO-8859-* / Windows-* / KOI8-* / CP866 | Одинаковые байты за пределами ASCII могут означать разные буквы. Допустимость байтов не доказывает выбор таблицы |
| EUC-JP, SJIS, ISO-2022-JP и их варианты | Различаются и схема байтов, и таблицы соответствий; названия не взаимозаменяемы |
| UTF-7 / UTF7-IMAP | Специализированные исторические форматы; не выбирать вместо UTF-8 для нового HTML |
| Base64 / QPrint / UUencode / HTML-ENTITIES | Это представление байтов/сущностей, а не обычная кодировка текста; применение через mbstring deprecated с 8.2 |
<?php
declare(strict_types=1);
$source = "\xCC\xE8\xF0";
if (!mb_check_encoding($source, 'Windows-1251')) {
throw new RuntimeException('Неверный вход');
}
$title = mb_convert_encoding($source, 'UTF-8', 'Windows-1251');
echo $title, "\n", mb_strlen($title, 'UTF-8');
Ожидаемый результат
Мир
3Байты записаны явно, поэтому пример не зависит от кодировки редактора. Проверка не доказывает, что файл действительно Windows-1251: это известно из договора с источником. Нельзя заменить такую договорённость бесконечным перебором кодировок.
BOM — маркер определённого формата, а не мусор в любом месте строки. Удалять известный UTF-8 BOM можно только в начале соответствующего файла; trim не предназначен для универсального исправления неизвестных байтов. UTF-8 допускает многие визуально похожие знаки: ни успешная проверка, ни перевод в нижний регистр не защищают от подмены идентификатора. Для входного JSON сначала проверяют размер и кодировку, затем структуру и прикладные поля.
Полный каталог имён: поддержка и назначение
Ниже сохранены семейства и варианты из официального списка; конкретная сборка сообщает свой каталог через mb_list_encodings, а синонимы — через mb_encoding_aliases. Псевдоним — второе имя той же таблицы, не доказательство совместимости разных таблиц. Возможности regex уже возможностей преобразования; например UTF-7/ISO-2022-JP не следует автоматически переносить в mb_regex_encoding.
| Группа | Имена и специальные варианты |
|---|---|
| Unicode и фиксированные единицы | UCS-4, UCS-4BE, UCS-4LE; UCS-2, UCS-2BE, UCS-2LE; UTF-32, UTF-32BE, UTF-32LE; UTF-16, UTF-16BE, UTF-16LE; UTF-7, UTF7-IMAP, UTF-8; byte2be, byte2le, byte4be, byte4le |
| Японские таблицы | EUC-JP, SJIS, eucJP-win, SJIS-win, ISO-2022-JP, ISO-2022-JP-MS, CP932, CP51932, SJIS-mac (MacJapanese), JIS, JIS-ms, CP50220, CP50220raw, CP50221, CP50222 |
| Японские мобильные legacy-таблицы | SJIS-Mobile#DOCOMO (SJIS-DOCOMO); SJIS-Mobile#KDDI (SJIS-KDDI); SJIS-Mobile#SOFTBANK (SJIS-SOFTBANK); UTF-8-Mobile#DOCOMO (UTF-8-DOCOMO); UTF-8-Mobile#KDDI-A; UTF-8-Mobile#KDDI-B (UTF-8-KDDI); UTF-8-Mobile#SOFTBANK (UTF-8-SOFTBANK); ISO-2022-JP-MOBILE#KDDI (ISO-2022-JP-KDDI) |
| ASCII и ISO | ASCII; ISO-8859-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -13, -14, -15, -16 |
| Китайские / корейские | EUC-CN, CP936, GB18030, HZ, EUC-TW, CP950, BIG-5; EUC-KR, UHC (CP949), ISO-2022-KR |
| Другие региональные | Windows-1251 (CP1251), Windows-1252 (CP1252), CP866 (IBM866), KOI8-R, KOI8-U, ArmSCII-8 (ArmSCII8) |
| Исторические нетекстовые имена | BASE64, HTML-ENTITIES (HTML), 7bit, 8bit; runtime-каталог также может содержать UUENCODE и Quoted-Printable. Наличие имени не делает его современным рекомендуемым API |
В официальном перечне для regex отмечены UCS-4/UCS-4LE; UTF-32 и его BE/LE, UTF-16 и его BE/LE; UTF-8, ASCII, EUC-JP, SJIS, eucJP-win, SJIS-win; перечисленные ISO-8859; EUC-CN, EUC-TW, BIG-5, EUC-KR, KOI8-R/KOI8-U. Это не обещание, что произвольный alias/новое имя примет каждая сборка: mb_regex_encoding проверяет свой поддерживаемый набор.
auto в списках кандидатов разворачивается в набор языкового профиля, например Japanese: ASCII, JIS, UTF-8, EUC-JP, SJIS. Это не универсальная кодировка, которую нужно передавать любому параметру encoding: mb_strlen(..., auto) не является способом распознать вход. pass в поддерживающих его настройках означает отсутствие преобразования; это не текстовая таблица. Кандидаты определяют допустимую область угадывания, а не происхождение данных.
Японский импорт: ширина, kana и таблица CP932
Zen-kaku обозначает широкие, han-kaku — узкие формы. Их вид зависит от шрифта; ширина на экране и количество байтов не совпадают. В японском legacy-обмене один знак мог занимать до нескольких байтов, а ISO-2022 использует переключающие escape-последовательности. Нельзя считать, что «японская буква всегда два байта» или что одна смена ширины исправит файл.
SJIS/Shift_JIS по стандартной таблице отличается от Windows CP932; для Windows-данных используется договорённый SJIS-win/CP932. Аналогично EUC-JP и eucJP-win различаются расширениями IBM/NEC. Сначала выясняют таблицу источника, затем меняют представление. Старые i-mode/EZweb и мобильные emoji имели собственные таблицы: поддержка нужна для миграции архива, а не как рекомендация строить новый сайт на Shift_JIS. Исторический совет ISO-2022-JP для SMTP отражает совместимость старых клиентов; современный формат письма согласуют с используемой библиотекой и транспортом.
<?php
declare(strict_types=1);
$record = "01" . mb_convert_encoding('東京', 'SJIS-win', 'UTF-8') . "07";
$cityBytes = substr($record, 2, 4);
$city = mb_convert_encoding($cityBytes, 'UTF-8', 'SJIS-win');
echo $city, "\n", substr($record, 6, 2), "\n";
echo strlen($cityBytes), ' -> ', strlen($city);
Ожидаемый результат
東京
07
4 -> 6В учебной схеме город занимает строго четыре байта SJIS-win и поле заканчивается на границе знака. Смещение следующего поля 6 относится к исходному record. Если сначала преобразовать всю запись в UTF-8, старое смещение уже неверно. Для реального файла нужна его спецификация, а не подбор чисел по одному образцу.
Преобразование kana mb_convert_kana полезно для согласованного поиска адресов/наименований, но сохраните оригинальное отображаемое имя. Широкие цифры, латиница, пробел, хирагана, катакана и знак озвончения требуют разных флагов; функция не является общей транслитерацией японского текста.
Режимы Unicode: обычное преобразование и simple
| Константы | Контракт |
|---|---|
| MB_CASE_UPPER / LOWER / TITLE | Верхний, нижний и начальный регистр слов; полные отображения могут увеличить число кодовых точек |
| MB_CASE_FOLD (с 7.3) | Сведение регистра для сравнения; это не красивый текст для вывода |
| MB_CASE_UPPER_SIMPLE / LOWER_SIMPLE / TITLE_SIMPLE / FOLD_SIMPLE (с 7.3) | Простое отображение без расширения в несколько кодовых точек. Сохранение количества точек не равно сохранению числа UTF-8 байтов |
| MB_ONIGURUMA_VERSION (с 7.4) | Строка версии regex-библиотеки, когда соответствующая возможность собрана |
| MB_OVERLOAD_MAIL / STRING / REGEX | Исторические биты 1/2/4; удалены с PHP 8.0 вместе с перегрузкой |
<?php
declare(strict_types=1);
$word = 'Straße';
echo mb_convert_case($word, MB_CASE_UPPER, 'UTF-8'), "\n";
echo mb_convert_case($word, MB_CASE_UPPER_SIMPLE, 'UTF-8'), "\n";
echo mb_convert_case($word, MB_CASE_FOLD, 'UTF-8');
Ожидаемый результат
STRASSE
STRAßE
strasseПолное uppercase расширяет ß в SS; simple сохраняет одну кодовую точку. Это правило Unicode, не ошибка UTF-8. Для конкретного печатного стандарта организации может потребоваться отдельное явно документированное правило, а не глобальная замена символов.
mbstring использует Unicode-данные версии 16.0 в PHP 8.4 и 17.0 в PHP 8.5. Изменения таблиц влияют на новые знаки и правила, поэтому сохранённые ключи поиска нельзя бездумно считать вечными между версиями. Смена регистра не является Unicode-нормализацией, языковой сортировкой или удалением диакритики.
HTTP: где именно происходит преобразование
- Входные байты запроса → SAPI разбирает форму
- Если заранее включён входной фильтр, он преобразует значения до пользовательского кода
- PHP проверяет типы/значения массива; это отдельная защита формы
- На выходе установленный output handler может преобразовать буфер согласно кодировке и MIME-типу
mbstring.encoding_translation может преобразовывать значения GET/POST/cookie и имена загруженных файлов multipart; имена ключей запроса этим механизмом не преобразуются. PHP-файл уже не управляет тем, как была разобрана форма. В новом JSON API обычно читают ожидаемый UTF-8 явно; изменение INI-фильтра не исправляет повреждённый JSON и не заменяет проверку схемы.
Для выходного преобразования нужны согласованные internal encoding, mb_http_output и зарегистрированный ob_start('mb_output_handler') либо серверный output_handler. Одно mb_http_output не перехватывает echo. Фильтр учитывает Content-Type и mbstring.http_output_conv_mimetypes; бинарный файл не должен проходить текстовую конверсию. Заголовки отправляют до тела. Двойное преобразование вручную и в буфере портит данные.
Удобнее хранить и выводить UTF-8 без скрытой конверсии. Legacy-клиент, которому действительно требуется Windows-1251, — отдельный пограничный маршрут с явным контрактом. Тело, HTTP-заголовок charset и байтовая длина должны согласоваться. Безопасная форма также требует метода запроса, CSRF при cookie-аутентификации, проверки каждого поля и контекстного экранирования: полный приём формы.
Исходный PHP-файл и удалённая перегрузка функций
Кодировка исходника — ещё один слой. Для обычного PHP-файла используйте UTF-8 без BOM. Старое правило книги требует ASCII-совместимых управляющих диапазонов и отсутствия конфликтов многобайтовых хвостов с синтаксисом PHP; JIS/ISO-2022-JP, SJIS, BIG5 и некоторые региональные таблицы в исходнике создавали проблемы разбора. Поддержка этих кодировок как данных не означает, что в них следует сохранять PHP-код. mb_internal_encoding не перенастраивает лексер автоматически.
В старом PHP mbstring.func_overload мог незаметно заменить mail на mb_send_mail (бит 1), строковые функции (бит 2) и исторические regex (бит 4); 7 объединяло биты. Это deprecated с 7.2 и удалено с 8.0. Старые советы о перегрузке по каталогу были особенно ненадёжны. В PHP 8 strlen всегда имеет свой байтовый смысл: новое приложение вызывает нужную функцию явно.
| Старые подменяемые функции | Явная замена, если нужна именно такая семантика |
|---|---|
| strlen, substr, substr_count | mb_strlen, mb_substr, mb_substr_count |
| strpos, strrpos, stripos, strripos | mb_strpos, mb_strrpos, mb_stripos, mb_strripos |
| strstr, stristr, strrchr | mb_strstr, mb_stristr, mb_strrchr |
| strtolower, strtoupper; mail | mb_strtolower, mb_strtoupper; mb_send_mail |
Не переписывайте весь проект механически: подпись запроса, длина бинарного пакета и лимит байтов должны остаться байтовыми. Для старой базы согласуйте кодировку соединения и хранимых данных; даже автоматическая конверсия драйвера не исправит ошибочную исходную метку. Универсальная «перекодировка до тех пор, пока выглядит нормально» теряет информацию.
Regex mbstring: шаблон, результат и общий курсор
Регулярное выражение описывает форму текста: [0-9]+ означает одну или несколько цифр, круглые скобки захватывают часть, ^ и $ ограничивают края по выбранному режиму. Здесь используется Oniguruma; у preg_* другой API и синтаксические настройки. Шаблон mb_ereg не обрамляют разделителями /…/u. Для обычной подстроки сначала рассмотрите mb_strpos, для фиксированного разделителя — explode.
- mb_ereg(pattern, text, matches) получает текст в каждом вызове
- mb_ereg_search_init(text, pattern) сохраняет один общий текст и курсор
- search/search_pos/search_regs ищут дальше и передвигают этот курсор
- getregs/getpos только читают результат/позицию; новый init заменит чужой поиск
У последовательного поиска позиции в байтах, у mb_strpos — в кодовых точках. Не передавайте их друг другу. Вложенная функция, которая вызовет mb_ereg_search_init, затрёт внешнее состояние: для независимых разборов удобнее явные аргументы или свой объект парсера. Предпочитайте шаблоны с непустым совпадением, ограничивайте вход и число извлечений; пустые совпадения и катастрофический backtracking требуют отдельной проверки, не бесконечного while.
Неверный шаблон обычно выдаёт E_WARNING и false; в заменах некорректные байты дают null. false нельзя всегда читать как «такого текста нет», если перед ним была ошибка компиляции/ресурсного предела. Ошибки callback не исчезают. Не подставляйте внешний текст как готовый шаблон и никогда не используйте исторический eval-флаг e: он удалён в PHP 8.0.
Найти нужную функцию и выбрать соседний инструмент
| Функция | Когда нужна |
|---|---|
mb_check_encoding | Поставщик обещает UTF-8, но в названии товара иногда приходит повреждённый байт. До поиска, записи и вывода нужно понять, соответствует ли строка этой договорённости. mb_check_encoding возвращает ответ да/нет; далее программа либо принимает данные, либо показывает причину отказа. Функция не восстанавливает испорченную букву. |
mb_chr | В таблице интеграции символ указан числом Unicode, например 8364 для евро. mb_chr создаёт из такого числа настоящую строку в нужной кодировке. Её можно включить в подпись цены или диагностическое сообщение. |
mb_convert_case | У преобразования регистра несколько разных задач: вывести заголовок, подготовить этикетку или сравнить два написания без регистра. mb_convert_case позволяет явно выбрать правило. Для сравнения Straße и STRASSE нужен полный case folding, а не простое приведение к строчным буквам. |
mb_convert_encoding | Старая складская программа выгружает названия в Windows-1251, а сайт работает в UTF-8. Слова должны остаться теми же, но последовательность байтов изменится. mb_convert_encoding получает исходные байты, кодировку назначения и известную кодировку источника. На выходе — новая строка или массив, с которыми уже можно работать в кодировке сайта. |
mb_convert_kana | Японский поставщик прислал артикул широкими символами AB12, а каталог хранит AB12. mb_convert_kana умеет согласованно менять ширину выбранных знаков и формы kana. Это помогает сопоставить данные по заранее выбранному правилу, сохраняя исходное написание. |
mb_convert_variables | Старый модуль отдаёт несколько связанных полей в одной кодировке и ожидает, что они будут изменены на месте. mb_convert_variables перекодирует переданные переменные по ссылке. Возвращаемое значение сообщает исходную кодировку; сами новые строки надо читать из тех переменных, которые передали. |
mb_decode_mimeheader | При импорте письма тема выглядит как =?UTF-8?B?...?=. Человеку нужно название, а не транспортная упаковка. mb_decode_mimeheader раскрывает encoded-word и возвращает текст в mb_internal_encoding. Она не разбирает вложения и не декодирует автоматически тело MIME-письма. |
mb_decode_numericentity | Партнёр передал знак евро в виде числовой HTML-ссылки, а отчёту нужна обычная UTF-8-строка. mb_decode_numericentity раскрывает ссылки только в выбранных диапазонах. После декодирования строка остаётся внешними данными и требует правил своего назначения. |
mb_detect_encoding | Файл пришёл без метки кодировки. Детектор может предложить кандидата из заданного списка, но не знает, что автор файла имел в виду. Поэтому сначала ищут договорённость с источником; автоматическую гипотезу используют для предпросмотра и подтверждения импорта, а не как доказательство правильного текста. |
mb_detect_order | Старый компонент вызывает mb_detect_encoding без списка кандидатов. mb_detect_order позволяет задать, какие таблицы он будет рассматривать по умолчанию. Это настройка детектора, а не команда перекодирования и не доказательство происхождения файла. |
mb_encode_mimeheader | В почтовом списке человек должен увидеть «Кисть», хотя транспортный заголовок содержит специальную ASCII-запись. mb_encode_mimeheader кодирует значение заголовка по MIME. Она не создаёт целое письмо и не отправляет его. Сначала получим одну строку Subject, затем сохраним собственный order.eml. |
mb_encode_numericentity | Иногда текстовый формат требует представить выбранные Unicode-знаки числовыми HTML-ссылками. Например, евро можно записать как € или €. Функция создаёт это представление по карте диапазонов; само по себе оно не является универсальным HTML-экранированием. |
mb_encoding_aliases | В настройке поставщика написано CP1251, а в вашем профиле — Windows-1251. Aliases помогают разобраться, являются ли это два имени одной таблицы. Это полезно при настройке интеграции; разные похожие кодировки нельзя объявлять одинаковыми только по названию. |
mb_ereg | В уведомлении поставщика есть номер заказа внутри текста: «Заказ 42 готов». mb_ereg ищет фрагмент по шаблону и возвращает захваченные части через отдельную переменную. Регистр букв по умолчанию важен; для варианта без регистра есть mb_eregi. |
mb_ereg_match | Перед поиском товара нужно принять артикул определённого вида: две латинские буквы, дефис, две цифры. mb_ereg_match начинает проверку с начала строки, но конец следует указать явно. Иначе правильный префикс может скрыть лишний текст. |
mb_ereg_replace | Редактору нужно привести подписи заказов к новому формату, сохранив номера. Замена по шаблону находит подпись и захватывает число, затем вставляет его в новый текст. mb_ereg_replace учитывает регистр, если явно не выбраны другие опции. |
mb_ereg_replace_callback | Текст уведомления содержит метки {{товар}} и {{город}}, а значения уже получены из заказа. Callback получает каждое найденное совпадение и возвращает подходящую подстановку. Так обычная PHP-функция участвует в построении текста без eval и без ручного поиска каждого места. |
mb_ereg_search | Текст и шаблон уже подготовлены через init. mb_ereg_search передвигается к следующему совпадению и сообщает, найдено ли оно. Сам найденный номер читают отдельной функцией getregs; когда больше номеров нет, цикл заканчивается. |
mb_ereg_search_getpos | Парсер уже прочитал один номер. Чтобы временно заглянуть вперёд и затем вернуться, нужно сохранить текущую позицию. getpos возвращает байтовый курсор следующего поиска, не изменяя его и не извлекая новый номер. |
mb_ereg_search_getregs | Найденный номер нужен и для подписи, и для следующего шага обработки. getregs читает группы последнего совпадения повторно, не переходя к следующему. Этим он отличается от search_regs, который сразу выполняет новый поиск. |
mb_ereg_search_init | Нужно последовательно извлечь номера из длинного уведомления, а не искать всё заново с начала. init сохраняет текст и шаблон для семейства mb_ereg_search_*. Это только подготовка: результат появится при следующем поисковом вызове. |
mb_ereg_search_pos | Кроме самого номера бывает нужно знать его место в исходном тексте: для разбора протокола, отметки проблемного участка или последующей замены. search_pos возвращает байтовое начало и длину следующего совпадения. Эти числа можно передать substr для той же неизменённой строки. |
mb_ereg_search_regs | Уведомление содержит пары «заказ — состояние». search_regs за один вызов находит следующую пару и возвращает группы: номер отдельно, состояние отдельно. Так текст можно превратить в обычные записи массива, которые дальше удобно перебирать. |
mb_ereg_search_setpos | После предварительного просмотра следующего номера нужно обработать его ещё раз. setpos возвращает курсор на сохранённую байтовую границу. Сам setter не ищет совпадение: результат появится только при следующем search-вызове. |
mb_eregi | В уведомлении поставщика есть номер заказа внутри текста: «ЗАКАЗ 42 готов». mb_eregi ищет фрагмент по шаблону и возвращает захваченные части через отдельную переменную. Регистр подписи при этом не важен. |
mb_eregi_replace | Редактору нужно привести подписи заказов к новому формату, сохранив номера. Замена по шаблону находит подпись и захватывает число, затем вставляет его в новый текст. mb_eregi_replace принимает разные регистры подписи. |
mb_get_info | На одном сервере письмо читается, на другом получается нечитаемая тема. Для диагностики нужны конкретные значения настройки mbstring: внутренняя кодировка, почтовый charset и способ упаковки. mb_get_info показывает их без огромной страницы phpinfo. |
mb_http_input | На страницу пришёл товар «Молоток». Нужно узнать, участвовал ли входной конвертер mbstring, и одновременно увидеть сами данные. mb_http_input читает состояние обработанного типа входа; она не возвращает содержимое формы и не определяет заново кодировку произвольной строки. Здесь согласован UTF-8, автоматическая конверсия выключена. |
mb_http_output | Читатель старой складской программы должен получить понятную строку «Молоток — 8 шт.». Задаёт желаемую выходную кодировку mbstring. Сам вызов не меняет уже существующие строки: нужен обработчик выходного буфера. Прежде чем подключать его к старому клиенту, сравним два настоящих ответа. |
mb_internal_encoding | Узнать или задать default для текстовых mb-функций. |
mb_language | Выбрать языковой профиль кодирования почты, а не язык пользовательского интерфейса. |
mb_lcfirst | Есть готовая подпись «Заказ готов», которую надо включить после слова «Статус:». mb_lcfirst делает строчной только первую кодовую точку: остальное написание остаётся как было. Это удобно для заранее подготовленных фраз, но не является редактором произвольного текста. |
mb_list_encodings | Форма импорта предлагает UTF-8 и старый Windows-1251. Перед обработкой нужно убедиться, что установленная сборка PHP поддерживает выбранные таблицы. mb_list_encodings возвращает каталог имён; из него приложение выбирает только форматы, которые действительно обещает обработать. |
mb_ltrim | После копирования названия из документа вокруг слова остаются неразрывные пробелы. mb_ltrim убирает выбранные знаки слева, сохраняя содержимое поля. Сначала увидим границы строки в квадратных скобках, затем подготовим название для карточки товара. Это осмысленная обработка текстового поля; пароли и подписанные данные так менять нельзя. |
mb_ord | Название выглядит нормально, но сравнение не проходит: в начале может стоять не обычный пробел, а NBSP. mb_ord возвращает числовой код первого символа. Это позволяет объяснить различие, которое на экране почти незаметно. |
mb_output_handler | Читатель старой складской программы должен получить понятную строку «Молоток — 8 шт.». Преобразует вывод только как зарегистрированный обработчик буфера. Сначала увидим режим pass: PHP собирает текст и передаёт его без изменения кодировки. Затем включим конверсию для старого клиента. |
mb_parse_str | Партнёр передал поля как строку product=...&stock=... . Требуется получить название, остаток и список меток, а затем проверить данные. mb_parse_str разбирает URL-encoded запись по правилам PHP и настроенного входного профиля; это не разбор JSON и не подтверждение корректности товара. |
mb_preferred_mime_name | Получить имя charset для протокольной метки. |
mb_regex_encoding | В старом приложении используются mb_ereg и другие функции Oniguruma. Чтобы русский шаблон находил русское название, движок должен одинаково читать шаблон и текст. mb_regex_encoding задаёт именно эту настройку; кодировка обычных mb-строк хранится отдельно. |
mb_regex_set_options | Один и тот же шаблон должен либо учитывать регистр, либо принимать «заказ» и «ЗАКАЗ». Опции задают это поведение и выбранный синтаксис mbregex. Они не совпадают с привычными флагами preg_match; особенно различается смысл m. |
mb_rtrim | После копирования названия из документа вокруг слова остаются неразрывные пробелы. mb_rtrim убирает выбранные знаки справа, сохраняя содержимое поля. Сначала увидим границы строки в квадратных скобках, затем подготовим название для карточки товара. Это осмысленная обработка текстового поля; пароли и подписанные данные так менять нельзя. |
mb_scrub | В диагностическом сообщении повреждён один байт, из-за чего дальнейшая Unicode-обработка ломается. mb_scrub заменяет недопустимые последовательности выбранным знаком. Так можно показать место повреждения в техническом отчёте; восстановить исходную букву эта функция не может. |
mb_send_mail | Нужно подготовить уведомление «Заказ 42: Кисть» и убедиться, какие тему и тело получил почтовый транспорт. В этом опыте транспорт — свой Python-приёмник на 127.0.0.1; он только сохраняет файл и не пересылает письмо. mb_send_mail выполняет MIME-кодирование по mb_language, затем передаёт результат почтовой подсистеме PHP. |
mb_split | В простом списке категорий пользователь может поставить запятую или точку с запятой. mb_split разбивает текст по regex-разделителю и возвращает массив. Когда разделитель один и буквально известен, достаточно explode; CSV с кавычками требует отдельного парсера. |
mb_str_pad | В текстовом списке нужно дополнить русское название до восьми кодовых точек, чтобы после него поставить разделитель. Обычная str_pad считает байты; mb_str_pad работает с кодовыми точками и добавляет указанное заполнение слева, справа или с двух сторон. |
mb_str_split | Для подсказки в учебной игре или диагностики текста нужно пройти по отдельным буквам русского слова. mb_str_split создаёт массив групп кодовых точек. Он не ищет разделитель, как explode: размер каждой группы задаётся числом. |
mb_strcut | Старое устройство принимает подпись максимум в девять байтов, а название хранится в UTF-8. mb_substr ограничивает символы, поэтому здесь нужен mb_strcut: он соблюдает байтовую границу, не оставляя половину многобайтового знака. Обрезка допустима только если это разрешает задача. |
mb_strimwidth | Колонка простого отчёта допускает шесть условных единиц ширины. Длинную подпись нужно сократить и показать две точки. mb_strimwidth учитывает и ширину знаков, и место маркера внутри общего бюджета. |
mb_stripos | В текстовой заметке нужно найти первое упоминание метки и получить его позицию. mb_stripos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр Unicode-букв при поиске не учитывается. |
mb_stristr | В подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от первого совпадения. mb_stristr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск не зависит от регистра Unicode-букв. |
mb_strlen | Форма разрешает название длиной до десяти символов. Для русского UTF-8-текста strlen посчитает байты, и короткое слово ошибочно покажется слишком длинным. mb_strlen считает кодовые точки: для обычного слова «Кисть» это пять букв. Составные видимые знаки требуют отдельного понятия графемы. |
mb_strpos | В текстовой заметке нужно найти первое упоминание метки и получить его позицию. mb_strpos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр букв учитывается: Кисть и кисть различаются. |
mb_strrchr | В подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от последнего совпадения. mb_strrchr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск учитывает регистр букв. |
mb_strrichr | В подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от последнего совпадения. mb_strrichr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск не зависит от регистра Unicode-букв. |
mb_strripos | В текстовой заметке нужно найти последнее упоминание метки и получить его позицию. mb_strripos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр Unicode-букв при поиске не учитывается. |
mb_strrpos | В текстовой заметке нужно найти последнее упоминание метки и получить его позицию. mb_strrpos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр букв учитывается: Кисть и кисть различаются. |
mb_strstr | В подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от первого совпадения. mb_strstr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск учитывает регистр букв. |
mb_strtolower | В поисковом поле покупатель написал «КИСТЬ», а товар называется «Кисть». Для простого русского поиска можно сравнить копии в нижнем регистре и вывести исходное название. mb_strtolower понимает Unicode-буквы; обычная strtolower для этой задачи с кириллицей не подходит. |
mb_strtoupper | Нужно напечатать крупную подпись на складской этикетке: «Кисть» превращается в «КИСТЬ». При этом некоторые Unicode-буквы разворачиваются в несколько букв, поэтому размер готовой подписи проверяют после преобразования. |
mb_strwidth | В простом текстовом отчёте есть латиница и японские названия. Две кодовые точки могут занимать разные условные ширины: AB считается как 2, 東京 — как 4. mb_strwidth помогает рассчитывать такую колонку, но не измеряет пиксели страницы. |
mb_substitute_character | При преобразовании строки встречается символ, которого нет в целевой кодировке. Настройка mb_substitute_character определяет, будет ли виден знак замены, код потерянного символа или вообще ничего. От этого зависит, заметит ли человек повреждение; исходную информацию подстановка не сохраняет. |
mb_substr | Нужно получить короткое превью русского названия, не обрывая UTF-8-букву посередине. mb_substr выбирает часть по позициям кодовых точек. Сначала возьмём слово из известной строки, затем добавим многоточие только там, где название действительно сокращено. |
mb_substr_count | Перед сборкой уведомления нужно узнать, сколько раз шаблон использует метку номера заказа. mb_substr_count считает неперекрывающиеся вхождения буквальной подстроки. Это не число слов и не поиск по регулярному выражению. |
mb_trim | После копирования названия из документа вокруг слова остаются неразрывные пробелы. mb_trim убирает выбранные знаки с обоих краёв, сохраняя содержимое поля. Сначала увидим границы строки в квадратных скобках, затем подготовим название для карточки товара. Это осмысленная обработка текстового поля; пароли и подписанные данные так менять нельзя. |
mb_ucfirst | Составленная подпись начинается со строчной буквы: «заказ готов». mb_ucfirst переводит первый знак в начальную форму регистра, сохраняя остальную строку. Для русской буквы это привычная заглавная; для некоторых Unicode-диграфов начальная и полностью верхняя формы различаются. |
Упражнение: одно имя для двух потребителей. Из импорта пришла UTF-8 строка «Кружка». Форма принимает максимум 10 кодовых точек; старый протокол разрешает подпись не длиннее 8 байтов. Для этой учебной подписи обрезка разрешена. Сначала отвергните повреждённый UTF-8, затем проверьте правило формы и подготовьте отдельную подпись для протокола, сохранив исходное имя. До запуска предскажите, сколько букв останется. Измените требование: теперь приёмнику нужно полное имя — какая ветка программы должна поменяться?
Предложенное решение. Проверка mb_check_encoding с явным UTF-8 должна вернуть true; mb_strlen даст 6, поэтому правило формы выполнено. mb_strcut с аргументами 0, 8 и UTF-8 вернёт «Круж»: четыре кириллические буквы занимают восемь байтов. Полную строку храним отдельно; после подготовки подписи сверяем strlen с байтовым бюджетом. Если требуется полное имя, вместо обрезки сравниваем исходный байтовый размер 12 с лимитом 8 и возвращаем понятную ошибку. Повторите шаги с составным emoji: проверка кодовых точек не обещает число видимых знаков. Исполняемые варианты этих операций приведены в карточках выше; упражнение проверяет выбор контракта, а не запоминание названия функции.
Регулярные выражения preg_* относятся к PCRE, grapheme_* и Normalizer — к intl, iconv_* — к iconv. Их возможности не включаются установкой mbstring. Для обычного разделителя подходит explode; для точной замены корректной UTF-8 подстроки часто достаточно str_replace. Выбор определяется задачей, а не обязательным префиксом mb_.
Функции и методы этой темы
Откройте карточку, чтобы увидеть договор функции, примеры, ограничения и связанные инструменты.
mb_check_encodingПоставщик обещает UTF-8, но в названии товара иногда приходит повреждённый байт. До поиска, записи и вывода нужно понять, соответствует ли строка этой договорённости. mb_check_encoding возвращает ответ да/нет; далее программа либо принимает данные, либо показывает причину отказа. Функция не восстанавливает испорченную букву.
PHP 4.4.3 / 5.1.3+ · mbstring
mb_check_encoding(array|string|null $value = null, ?string $encoding = null): bool- Правильное название Кисть проходит проверку UTF-8.
- Байт FF в Ки\xFFсть не является допустимым UTF-8.
- Повреждённую строку отклоняем, а не выдаём за исправленное название.
| Аргумент / результат | Что передать и получить |
|---|---|
| value | Строка либо массив; в массиве рекурсивно проверяются и строковые ключи, и значения. Числа/boolean не превращаются в пользовательский текст. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | true — все проверенные строки допустимы; false — найдены недопустимые байты. Это не определение происхождения текста. |
<?php
$title = 'Кисть';
var_dump(mb_check_encoding($title, 'UTF-8'));
var_dump(mb_check_encoding("Ки\xFFсть", 'UTF-8'));
Ожидаемый результат
bool(true)
bool(false)
var_dump показывает тип bool явно; echo для false вывел бы пустоту. \xFF в двойной строке создаёт один намеренно неправильный байт. Проверка не меняет $title и не сравнивает его с каталогом.
<?php
$rows = ['Кисть', "Мо\xFFлоток", 'Валик'];
foreach ($rows as $index => $title) {
if (!mb_check_encoding($title, 'UTF-8')) {
echo 'Строка ', $index + 1, ": повреждён UTF-8, товар не принят\n";
continue;
}
echo 'Принят товар: ', $title, "\n";
}
Ожидаемый результат
Принят товар: Кисть
Строка 2: повреждён UTF-8, товар не принят
Принят товар: Валик
Нумерация для человека начинается с единицы. continue пропускает обработку повреждённого значения и переходит к следующему. Это проверка локального массива до реальной записи в базу. Название всё ещё проверяют по длине и правилам каталога; корректный UTF-8 не означает безопасный HTML.
<?php
$order = ['customer' => ['name' => 'Анна'], 'quantity' => 2];
echo mb_check_encoding($order, 'UTF-8') ? "Пакет читается как UTF-8\n" : "Повреждён пакет\n";
$order['customer']["note\xFF"] = 'Позвонить';
echo mb_check_encoding($order, 'UTF-8') ? "Пакет читается как UTF-8\n" : "Повреждён ключ или значение\n";
Ожидаемый результат
Пакет читается как UTF-8
Повреждён ключ или значение
Массив проверяется рекурсивно, включая строковые ключи. Функция не сообщает путь к плохому элементу: для подробного отчёта нужен собственный обход. Размер и глубину внешнего пакета ограничивают до обработки. Число quantity остаётся числом; проверка кодировки не проверяет схему заказа.
Ошибки и границы. Массивы поддерживаются с 7.2; пропуск value или null deprecated с 8.1 (старое значение означало проверку входа запроса). Передавайте конкретные данные. encoding nullable с 8.0; неизвестная кодировка — ValueError. Состоящий из ASCII текст допустим во многих кодировках; true не выбирает одну из них.
Рядом: mb_detect_encoding, mb_scrub, mb_convert_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_detect_encodingФайл пришёл без метки кодировки. Детектор может предложить кандидата из заданного списка, но не знает, что автор файла имел в виду. Поэтому сначала ищут договорённость с источником; автоматическую гипотезу используют для предпросмотра и подтверждения импорта, а не как доказательство правильного текста.
PHP 4.0.6+ · mbstring
mb_detect_encoding(string $string, array|string|null $encodings = null, bool $strict = false): string|false- Байты сравниваются с разрешёнными таблицами.
- Несколько таблиц могут принять одну последовательность.
- Известная метка источника надёжнее удачной на вид гипотезы.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исследуемые байты; короткая строка даёт особенно мало информации. |
| encodings | Массив имён или список через запятую; null/пропуск использует mb_detect_order. auto разворачивает языковой набор. |
| strict | true возвращает false, если ни один кандидат не допускает вход; false может выбрать ближайший даже для некорректной строки. Значение при пропуске также связано с mbstring.strict_detection. |
| return | Каноническое имя предполагаемой кодировки либо false; это не процент уверенности. |
<?php
$encoding = mb_detect_encoding('Кисть', ['UTF-8'], true);
echo 'Кандидат: ', $encoding, "\n";
$broken = mb_detect_encoding("\xFF", ['UTF-8'], true);
echo $broken === false ? "UTF-8 не подходит\n" : $broken;
Ожидаемый результат
Кандидат: UTF-8
UTF-8 не подходит
true включает строгую проверку допустимости байтов. При одном кандидате понятен смысл опыта: это не угадывание языка. Для простой проверки известного UTF-8 короче использовать mb_check_encoding.
<?php
$bytes = "\xC4\xA2";
foreach (['UTF-8', 'Windows-1252'] as $encoding) {
if (mb_check_encoding($bytes, $encoding)) {
echo $encoding, ': ', mb_convert_encoding($bytes, 'UTF-8', $encoding), "\n";
}
}
$candidate = mb_detect_encoding($bytes, ['UTF-8', 'Windows-1252'], true);
echo $candidate === false ? "Нет кандидата\n" : "Есть гипотеза; источник ещё неизвестен\n";
Ожидаемый результат
UTF-8: Ģ
Windows-1252: Ģ
Есть гипотеза; источник ещё неизвестен
Оба чтения допустимы, а смысл различается. Какой кандидат выберет эвристика, не фиксируем как бизнес-правило. После PHP 8.1 порядок списка не гарантирует выбор первой допустимой таблицы. Сохраняйте исходные байты и профиль импорта; неверную догадку нельзя выдавать за исправление.
Ошибки и границы. С 8.1 эвристика не обязана выбирать первый допустимый кандидат. С 8.2 нетекстовые Base64/QPrint/UUencode/HTML entities/7bit/8bit не являются результатом детектора. Неизвестное имя и пустой список — ValueError. strict=true доказывает допустимость в кандидате, а не правильность языка/смысла.
Рядом: mb_check_encoding, mb_detect_order, mb_convert_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_detect_orderСтарый компонент вызывает mb_detect_encoding без списка кандидатов. mb_detect_order позволяет задать, какие таблицы он будет рассматривать по умолчанию. Это настройка детектора, а не команда перекодирования и не доказательство происхождения файла.
PHP 4.0.6+ · mbstring
mb_detect_order(array|string|null $encoding = null): array|bool- Сохраняем предыдущий список.
- На время компонента разрешаем ASCII и UTF-8.
- После обработки возвращаем прежнюю настройку; сама строка не изменилась.
| Аргумент / результат | Что передать и получить |
|---|---|
| encoding | Массив имён/строка через запятую устанавливает список; null/пропуск читает текущий. auto раскрывается по языковому профилю. |
| return | При чтении — упорядоченный массив; при записи — true при успехе (контракт допускает false). |
<?php
$previous = mb_detect_order();
try {
mb_detect_order(['ASCII', 'UTF-8']);
echo 'Кандидаты: ', implode(', ', mb_detect_order()), "\n";
echo 'Для Кисть получено: ', mb_detect_encoding('Кисть', null, true), "\n";
} finally {
mb_detect_order($previous);
}
Ожидаемый результат
Кандидаты: ASCII, UTF-8
Для Кисть получено: UTF-8
null во втором аргументе детектора означает использовать default. Русские UTF-8-байты не допускаются ASCII, поэтому в этом ограниченном опыте выбор однозначен. В общем случае несколько таблиц принимают одинаковые байты, и порядок не гарантирует истинность результата.
<?php
$candidate = mb_detect_encoding('Кисть', ['UTF-8'], true);
if ($candidate === false) {
echo "Файл не соответствует договорённому UTF-8\n";
} else {
echo 'Для предпросмотра выбран ', $candidate, ': Кисть', "\n";
}
Ожидаемый результат
Для предпросмотра выбран UTF-8: Кисть
Если управляете самим вызовом, явный список проще общей настройки. mb_detect_order нужен для совместимости с компонентом, который список не передаёт. При известном контракте UTF-8 обычно достаточно mb_check_encoding вместо эвристики.
Ошибки и границы. В PHP 8 неверное имя — ValueError; null разрешён с 8.0. Старый текст страницы о «всегда неверном UTF-16/32» и гарантированном первом совпадении не описывает современный движок: на 8.5.11 UTF-16LE проверяется. Однобайтовые таблицы допускают множество любых последовательностей, поэтому широкий список не улучшает доказательность.
Рядом: mb_detect_encoding, mb_language, mb_internal_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_list_encodingsФорма импорта предлагает UTF-8 и старый Windows-1251. Перед обработкой нужно убедиться, что установленная сборка PHP поддерживает выбранные таблицы. mb_list_encodings возвращает каталог имён; из него приложение выбирает только форматы, которые действительно обещает обработать.
PHP 5+ · mbstring
mb_list_encodings(): array- Расширение возвращает массив поддерживаемых имён.
- Приложение пересекает его со своим небольшим списком форматов.
- Пользователь видит подходящие варианты импорта, а не все исторические кодировки подряд.
| Аргумент / результат | Что передать и получить |
|---|---|
| Параметры | Нет; результат относится к текущему установленному расширению. |
| return | Массив строк с числовыми ключами. Набор и порядок не стоит фиксировать как контракт приложения. |
<?php
$supported = mb_list_encodings();
$wanted = ['UTF-8', 'Windows-1251', 'ASCII'];
$available = array_intersect($wanted, $supported);
foreach ($available as $encoding) {
echo 'Можно выбрать: ', $encoding, "\n";
}
Ожидаемый результат
Можно выбрать: UTF-8
Можно выбрать: Windows-1251
Можно выбрать: ASCII
$supported — полный массив. array_intersect оставляет только значения, присутствующие в обоих списках; порядок здесь берётся из $wanted. Перечисление ещё не преобразовало ни одного файла. Полный состав сборки можно просмотреть через foreach ($supported as $encoding).
<?php
$allowed = ['UTF-8', 'Windows-1251'];
$selected = 'Windows-1251';
if (!in_array($selected, $allowed, true)
|| !in_array($selected, mb_list_encodings(), true)) {
throw new InvalidArgumentException('Этот профиль импорта недоступен');
}
$bytes = "\xCA\xE8\xF1\xF2\xFC";
echo 'Импортировано название: ', mb_convert_encoding($bytes, 'UTF-8', $selected), "\n";
Ожидаемый результат
Импортировано название: Кисть
Два условия отвечают за разные вещи: разрешение формата вашим приложением и его поддержку PHP. true у in_array включает строгое сравнение. Название кодировки должно соответствовать договорённости с поставщиком; наличие таблицы не доказывает, что именно ею записан файл.
Ошибки и границы. Документация не указывает специальных ошибок корректного вызова без аргументов. Отсутствие самого расширения — Error при попытке вызвать функцию. Список конвертера не равен списку mbregex.
Рядом: mb_encoding_aliases, mb_preferred_mime_name, mb_get_info. Байты, кодовые точки и графемы; общие правила вызова.
mb_encoding_aliasesВ настройке поставщика написано CP1251, а в вашем профиле — Windows-1251. Aliases помогают разобраться, являются ли это два имени одной таблицы. Это полезно при настройке интеграции; разные похожие кодировки нельзя объявлять одинаковыми только по названию.
PHP 5.3+ · mbstring
mb_encoding_aliases(string $encoding): array- Основное имя UTF-8 имеет известный псевдоним utf8.
- Каталог имён позволяет объяснить такое написание в конфигурации.
- Перекодирование выполняет другая функция; чтение aliases само текст не меняет.
| Аргумент / результат | Что передать и получить |
|---|---|
| encoding | Известное имя таблицы, например Windows-1251. |
| return | Массив alias-строк; может быть пустым. Основное имя не обязано входить в aliases. |
<?php
$aliases = mb_encoding_aliases('UTF-8');
foreach ($aliases as $alias) {
echo 'Альтернативное имя: ', $alias, "\n";
}
Ожидаемый результат
Альтернативное имя: utf8
Функция возвращает массив, а не строку через запятую. Основное имя не обязано входить в aliases. Этот результат относится к проверенной сборке; код не должен зависеть от номера конкретного элемента.
<?php
$aliases = array_map('strtolower', mb_encoding_aliases('Windows-1251'));
if (in_array('cp1251', $aliases, true)) {
$bytes = "\xCA\xE8\xF1\xF2\xFC";
echo 'CP1251 читается как Windows-1251: ', mb_convert_encoding($bytes, 'UTF-8', 'CP1251'), "\n";
}
Ожидаемый результат
CP1251 читается как Windows-1251: Кисть
array_map меняет регистр только ASCII-имён для проверки, не байты файла. Сам список aliases не является разрешением принять любой профиль пользователя: приложение по-прежнему ограничивает доступные форматы.
<?php
try {
mb_encoding_aliases('vendor-unknown-encoding');
} catch (ValueError $error) {
echo "Уточните кодировку у поставщика: такой таблицы PHP не знает\n";
}
Ожидаемый результат
Уточните кодировку у поставщика: такой таблицы PHP не знает
Нельзя молча заменить неизвестную таблицу на UTF-8 и объявить импорт успешным. В PHP 8 возникает ValueError; старые версии сообщали warning/false. Широкий catch всех ошибок без объяснения скрыл бы ошибку настройки.
Ошибки и границы. С PHP 8 неизвестное имя вызывает ValueError; раньше были E_WARNING и false. Alias не делает Shift_JIS и CP932 идентичными.
Рядом: mb_list_encodings, mb_preferred_mime_name, mb_convert_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_preferred_mime_nameПолучить имя charset для протокольной метки.
PHP 4.0.6+ · mbstring
mb_preferred_mime_name(string $encoding): string|false- В программе используется alias
- Функция возвращает имя для charset
- Байты тела всё равно нужно получить в этой кодировке
| Аргумент / результат | Что передать и получить |
|---|---|
| encoding | Известное mbstring имя кодировки. |
| return | Предпочтительное MIME-имя; false, если предпочтительного имени нет. Это не уже готовый заголовок. |
<?php
declare(strict_types=1);
echo mb_preferred_mime_name('utf8');
Ожидаемый результат
UTF-8Возвращённая строка не меняет ни данные, ни заголовки HTTP.
<?php
declare(strict_types=1);
$encoding = 'Windows-1251';
$charset = mb_preferred_mime_name($encoding);
if ($charset === false) { throw new RuntimeException('Нет MIME-имени'); }
$body = mb_convert_encoding('Мир', $encoding, 'UTF-8');
echo 'charset=', $charset, "\nbytes=", strlen($body);
Ожидаемый результат
charset=Windows-1251
bytes=3Это локальная подготовка тела и метки; реальную отправку header() пример не имитирует. Для HTML всё равно нужно контекстное экранирование.
Ошибки и границы. Неизвестное имя в PHP 8.5 вызывает ValueError. false с E_WARNING — другая ситуация, известная таблица без предпочтительного MIME-имени. Не подставляйте произвольную строку пользователя в заголовок.
Рядом: mb_encoding_aliases, mb_http_output, mb_encode_mimeheader. Байты, кодовые точки и графемы; общие правила вызова.
mb_internal_encodingУзнать или задать default для текстовых mb-функций.
PHP 4.0.6+ · mbstring
mb_internal_encoding(?string $encoding = null): string|bool- Строковые байты уже существуют
- Меняется только default для будущих вызовов без encoding
- Явный encoding у вызова имеет свой смысл независимо от default
| Аргумент / результат | Что передать и получить |
|---|---|
| encoding | Имя устанавливает default; null/пропуск читает его. |
| return | При чтении строка; при успешной записи true, контракт включает false. |
<?php
declare(strict_types=1);
$old = mb_internal_encoding();
try {
mb_internal_encoding('UTF-8');
echo mb_internal_encoding(), ': ', mb_strlen('Дом');
} finally { mb_internal_encoding($old); }
Ожидаемый результат
UTF-8: 3Второй аргумент mb_strlen пропущен намеренно, чтобы увидеть default. Для библиотечного кода явная кодировка часто понятнее.
<?php
declare(strict_types=1);
$bytes = "\xCC\xE8\xF0";
$old = mb_internal_encoding();
try {
mb_internal_encoding('UTF-8');
echo bin2hex($bytes), "\n";
echo mb_convert_encoding($bytes, 'UTF-8', 'Windows-1251');
} finally { mb_internal_encoding($old); }
Ожидаемый результат
cce8f0
Мирbin2hex показывает исходные байты. Только второй вызов выполняет преобразование с известной исходной таблицей.
Ошибки и границы. Неизвестная кодировка — ValueError с 8.0 (раньше warning/false); null разрешён с 8.0. Эта функция не меняет отдельную regex-кодировку и не перенастраивает соединение БД. Устарела INI-директива mbstring.internal_encoding, а не сама функция.
Рядом: mb_convert_encoding, mb_regex_encoding, mb_get_info. Байты, кодовые точки и графемы; общие правила вызова.
mb_substitute_characterПри преобразовании строки встречается символ, которого нет в целевой кодировке. Настройка mb_substitute_character определяет, будет ли виден знак замены, код потерянного символа или вообще ничего. От этого зависит, заметит ли человек повреждение; исходную информацию подстановка не сохраняет.
PHP 4.0.6+ · mbstring
mb_substitute_character(string|int|null $substitute_character = null): string|int|bool- Стоимость 5 € нужно выразить в ASCII.
- Евро не существует в ASCII.
- Выбранный режим даёт 5 ?, 5 U+20AC или 5 без знака валюты — это разные последствия потери.
| Аргумент / результат | Что передать и получить |
|---|---|
| substitute_character | Unicode codepoint числом, например 0xFFFD; либо none (удаление), long (описание кода), entity (числовая сущность). null читает текущую настройку. |
| return | Чтение: int/строка; запись: true при успехе, контракт включает false. |
<?php
$old = mb_substitute_character();
try {
mb_substitute_character(ord('?'));
echo mb_convert_encoding('5 €', 'ASCII', 'UTF-8'), "\n";
} finally {
mb_substitute_character($old);
}
Ожидаемый результат
5 ?
ord получает числовой код ASCII-знака ?. Настройка действует на последующие преобразования, а не меняет строку сама. После примера прежнее правило возвращается.
<?php
$old = mb_substitute_character();
try {
foreach (['long', 'entity', 'none'] as $mode) {
mb_substitute_character($mode);
echo $mode, ': [', mb_convert_encoding('5 €', 'ASCII', 'UTF-8'), "]\n";
}
} finally {
mb_substitute_character($old);
}
Ожидаемый результат
long: [5 U+20AC]
entity: [5 €]
none: [5 ]
Квадратные скобки показывают оставшийся пробел. none удалил сам знак валюты, а entity записал техническую последовательность, которую обычный текстовый приёмник может показать буквально. Для цены правильнее согласовать UTF-8 или явное обозначение EUR, чем молча потерять валюту.
Ошибки и границы. Недопустимый codepoint/строка режима — ValueError. С 8.0 пустая строка не означает удаление: для этого есть none. Настройка влияет также на output handler и почту; не оставляйте её изменённой в worker.
Рядом: mb_scrub, mb_convert_encoding, mb_convert_variables. Байты, кодовые точки и графемы; общие правила вызова.
mb_scrubВ диагностическом сообщении повреждён один байт, из-за чего дальнейшая Unicode-обработка ломается. mb_scrub заменяет недопустимые последовательности выбранным знаком. Так можно показать место повреждения в техническом отчёте; восстановить исходную букву эта функция не может.
PHP 7.2+ · mbstring
mb_scrub(string $string, ?string $encoding = null): string- Ки\xFFсть содержит байт, не читаемый как UTF-8.
- Настройка замены U+FFFD означает видимый знак �.
- Результат Ки�сть читается как UTF-8, но исходное название всё ещё потеряно.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Повреждённые или корректные байты. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка той же кодировки с подстановками согласно mb_substitute_character. |
<?php
$old = mb_substitute_character();
try {
mb_substitute_character(0xFFFD);
$clean = mb_scrub("Ки\xFFсть", 'UTF-8');
echo $clean, "\n";
echo mb_check_encoding($clean, 'UTF-8') ? "Результат имеет допустимые байты\n" : "Ошибка\n";
} finally {
mb_substitute_character($old);
}
Ожидаемый результат
Ки�сть
Результат имеет допустимые байты
0xFFFD — код знака замены. try/finally здесь сохраняет общую настройку для остального приложения. Допустимость результата не доказывает правильность слова; очищенную копию нельзя считать исходными данными заказа.
<?php
$old = mb_substitute_character();
try {
mb_substitute_character(0xFFFD);
$raw = "Ки\xFFсть";
if (!mb_check_encoding($raw, 'UTF-8')) {
echo 'Строка 7 отклонена. Диагностическая копия: ', mb_scrub($raw, 'UTF-8'), "\n";
echo 'Исходные байты: ', bin2hex($raw), "\n";
}
} finally {
mb_substitute_character($old);
}
Ожидаемый результат
Строка 7 отклонена. Диагностическая копия: Ки�сть
Исходные байты: d09ad0b8ffd181d182d18c
Номер строки помогает попросить поставщика исправить конкретную запись. Пример использует учебное название без секретов. В реальном журнале ограничивают объём и доступ; scrub не скрывает личные данные и не заменяет htmlspecialchars при HTML-выводе.
Ошибки и границы. Неизвестная кодировка — ValueError; nullable encoding с 8.0. Для подписи, пароля, платёжного идентификатора исправление с потерями меняет смысл: такой вход обычно отклоняют.
Рядом: mb_check_encoding, mb_substitute_character, mb_convert_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_get_infoНа одном сервере письмо читается, на другом получается нечитаемая тема. Для диагностики нужны конкретные значения настройки mbstring: внутренняя кодировка, почтовый charset и способ упаковки. mb_get_info показывает их без огромной страницы phpinfo.
PHP 4.2+ · mbstring
mb_get_info(string $type = "all"): array|string|int|false|null- Настройка internal_encoding описывает чтение исходного текста.
- mail_charset и mail_header_encoding описывают подготовку заголовка письма.
- Снимок помогает сравнить окружения, но сам письмо не отправляет и не исправляет.
| Аргумент / результат | Что передать и получить |
|---|---|
| type | all или пропуск возвращает набор. Отдельные ключи перечислены ниже; это не имя произвольной INI-директивы. |
| return | Массив при all; значение соответствующего типа при выбранном ключе; false для неизвестного ключа. |
Доступны internal_encoding, http_input, http_output, http_output_conv_mimetypes, mail_charset, mail_header_encoding, mail_body_encoding, illegal_chars, encoding_translation, language, detect_order, substitute_character, strict_detection. illegal_chars — счётчик проблем преобразования в данном контексте, не карта повреждённых мест в конкретной строке. Regex-настройку получают отдельно через mb_regex_encoding.
<?php
$old = mb_internal_encoding();
try {
mb_internal_encoding('UTF-8');
echo 'Исходный текст: ', mb_get_info('internal_encoding'), "\n";
} finally {
mb_internal_encoding($old);
}
Ожидаемый результат
Исходный текст: UTF-8
Строка internal_encoding выбирает конкретное поле. Это чтение информации, а не запись настройки. Настройку перед этим меняет отдельная функция mb_internal_encoding.
<?php
$language = mb_language();
$encoding = mb_internal_encoding();
try {
mb_language('neutral');
mb_internal_encoding('UTF-8');
$info = mb_get_info();
foreach (['internal_encoding', 'mail_charset', 'mail_header_encoding', 'mail_body_encoding'] as $key) {
echo $key, ': ', $info[$key], "\n";
}
} finally {
mb_language($language);
mb_internal_encoding($encoding);
}
Ожидаемый результат
internal_encoding: UTF-8
mail_charset: UTF-8
mail_header_encoding: BASE64
mail_body_encoding: BASE64
Это конкретный профиль neutral. На чужом сервере значения могут отличаться, поэтому вывод читают, а не подменяют проверкой наличия ключей. Кодирование заголовка и тела — отдельные поля. Диагностику показывают администратору, а не каждому посетителю сайта.
Ошибки и границы. Неизвестный type возвращает false с E_WARNING. Не отдавайте диагностические настройки публичным endpoint без необходимости: для формы важнее понятная ошибка поля, чем детали сервера.
Рядом: mb_internal_encoding, mb_detect_order, mb_language. Байты, кодовые точки и графемы; общие правила вызова.
mb_languageВыбрать языковой профиль кодирования почты, а не язык пользовательского интерфейса.
PHP 4.0.6+ · mbstring
mb_language(?string $language = null): string|bool- Почтовый legacy-профиль задаёт charset и переносимое представление
- mb_send_mail использует этот профиль
- Сам текст не переводится, регистр не становится локалезависимым
| Аргумент / результат | Что передать и получить |
|---|---|
| language | Поддерживаемое имя/alias профиля; null/пропуск читает текущий. |
| return | Строка при чтении, true при успешной записи; сигнатура включает false. |
| Профиль / alias | Charset; кодирование заголовка |
|---|---|
| German/de/Deutsch | ISO-8859-15; Quoted-Printable |
| English/en | ISO-8859-1; Quoted-Printable |
| Armenian/hy | ArmSCII-8; Quoted-Printable |
| Japanese/ja | ISO-2022-JP; Base64 |
| Korean/ko | ISO-2022-KR; Base64 |
| neutral; uni/universal | UTF-8; Base64 |
| Russian/ru | KOI8-R; Quoted-Printable |
| Turkish/tr | ISO-8859-9; Quoted-Printable |
| Ukrainian/ua | KOI8-U; Quoted-Printable |
| Simplified Chinese/zh-cn | HZ; Base64 |
| Traditional Chinese/zh-tw | BIG-5; Base64 |
Кодирование заголовка и Content-Transfer-Encoding тела — отдельные настройки профиля. В PHP 8.5.11 Japanese использует Base64 для заголовка, но 7bit для тела; English/Russian — Quoted-Printable для заголовка, 8bit для тела; neutral/uni — Base64 для обоих. Смотрите mb_get_info('mail_header_encoding') и mb_get_info('mail_body_encoding'), а не переносите одну колонку таблицы на всё письмо.
<?php
declare(strict_types=1);
$old = mb_language();
try { mb_language('neutral'); echo mb_get_info('mail_charset'); }
finally { mb_language($old); }
Ожидаемый результат
UTF-8Это чтение подготовки почты; письмо не отправляется.
<?php
declare(strict_types=1);
$old = mb_language();
try {
mb_language('Japanese');
echo 'Заказ готов', "\n", mb_get_info('mail_charset'), "\n";
echo mb_get_info('mail_header_encoding'), '/', mb_get_info('mail_body_encoding');
} finally { mb_language($old); }
Ожидаемый результат
Заказ готов
ISO-2022-JP
BASE64/7bitВыбор Japanese — совместимость с определённым почтовым получателем, а не автоматический перевод. В последних двух значениях видна разница упаковки заголовка и тела. Для нового многоязычного сервиса обычно удобнее согласованный UTF-8-профиль.
Ошибки и границы. В PHP 8.5 неизвестное имя языка вызывает ValueError, хотя историческое описание говорит о false. null разрешён с 8.0. Не меняет setlocale и не делает Unicode lowercase турецкой локализацией.
Рядом: mb_send_mail, mb_encode_mimeheader, mb_detect_order. Байты, кодовые точки и графемы; общие правила вызова.
mb_convert_encodingСтарая складская программа выгружает названия в Windows-1251, а сайт работает в UTF-8. Слова должны остаться теми же, но последовательность байтов изменится. mb_convert_encoding получает исходные байты, кодировку назначения и известную кодировку источника. На выходе — новая строка или массив, с которыми уже можно работать в кодировке сайта.
PHP 4.0.6+ · mbstring
mb_convert_encoding(array|string $string, string $to_encoding, array|string|null $from_encoding = null): array|string|false- Кисть в Windows-1251: ca e8 f1 f2 fc — пять байтов.
- Декодируем источник по Windows-1251, записываем результат по UTF-8.
- Кисть в UTF-8 занимает десять байтов и нормально выводится на UTF-8-странице.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Строка или массив; строковые значения и строковые ключи преобразуются рекурсивно, числовые ключи сохраняются. Исходная переменная не переписывается. |
| to_encoding | Кодировка результата. |
| from_encoding | Известная кодировка исходных байтов; null — internal/default_charset. Список кандидатов вызывает угадывание, а не последовательные конверсии. |
| return | Преобразованная строка/массив либо false при неудаче определения/преобразования. Потеря символа через подстановку не обязана дать false. |
<?php
$legacy = "\xCA\xE8\xF1\xF2\xFC";
$title = mb_convert_encoding($legacy, 'UTF-8', 'Windows-1251');
echo 'Название: ', $title, "\n";
echo 'Байтов до: ', strlen($legacy), '; после: ', strlen($title), "\n";
echo 'Исходные байты: ', bin2hex($legacy), "\n";
Ожидаемый результат
Название: Кисть
Байтов до: 5; после: 10
Исходные байты: cae8f1f2fc
Второй аргумент — куда, третий — откуда. Шестнадцатеричная запись нужна, чтобы UTF-8-файл примера действительно содержал старые байты в переменной. Это не транслитерация: слово осталось русским. Заголовок страницы с UTF-8 сам по себе не преобразует старую строку.
<?php
$legacyRow = "BR41;\xCA\xE8\xF1\xF2\xFC;12";
$utf8Row = mb_convert_encoding($legacyRow, 'UTF-8', 'Windows-1251');
$fields = str_getcsv($utf8Row, ';', '"', '');
echo 'Артикул: ', $fields[0], "\n";
echo 'Название: ', $fields[1], "\n";
echo 'Остаток из файла: ', $fields[2], "\n";
Ожидаемый результат
Артикул: BR41
Название: Кисть
Остаток из файла: 12
По контракту этой выгрузки разделитель — точка с запятой, исходная кодировка — Windows-1251. Сначала получаем нормальный текст, затем разбираем CSV. Для файла используют file_get_contents/fgetcsv или поток с согласованной перекодировкой; здесь показана одна строка. Перед записью проверяют число полей, тип и предел остатка: значение CSV пока строка.
<?php
$legacy = ["\xEA\xEE\xE4" => ['title' => "\xCA\xE8\xF1\xF2\xFC", 'stock' => 12]];
$catalog = mb_convert_encoding($legacy, 'UTF-8', 'Windows-1251');
echo 'Имя ключа: ', array_key_first($catalog), "\n";
echo $catalog['код']['title'], ': ', $catalog['код']['stock'], " шт.\n";
Ожидаемый результат
Имя ключа: код
Кисть: 12 шт.
Массив преобразуется рекурсивно, в том числе строковые ключи. stock был числом и остался числом. Смешивать кодировки разных строк в одном таком вызове нельзя. Потери и совпадение преобразованных ключей способны изменить данные; для важного импорта сохраняют оригинал и проверяют схему.
<?php
$old = mb_substitute_character();
try {
mb_substitute_character(ord('?'));
$name = 'Кисть';
$export = mb_convert_encoding($name, 'ASCII', 'UTF-8');
echo 'Экспорт: ', $export, "\n";
$roundTrip = mb_convert_encoding($export, 'UTF-8', 'ASCII');
if ($roundTrip !== $name) {
echo "Название потеряет символы — нужен другой формат экспорта\n";
}
} finally {
mb_substitute_character($old);
}
Ожидаемый результат
Экспорт: ?????
Название потеряет символы — нужен другой формат экспорта
Возврат строки не означает отсутствие потерь. Здесь обратное преобразование обнаруживает потерю именно этого значения; вопросительные знаки уже не содержат исходных букв. Нельзя исправить неверно выбранную таблицу подстановками «похожих» букв. Источник кодировки выясняют у поставщика.
Ошибки и границы. Массивы поддерживаются с 7.2; неизвестные имена — ValueError с 8.0, from nullable с 8.0. Объекты/ресурсы внутри массива не поддерживаются, предупреждения могут сопровождаться пропуском элемента; рекурсивные ссылки также не являются обычным деревом данных. Перед повторной конверсией убедитесь, что строка ещё в исходной кодировке. Base64/QPrint/UUencode/HTML-ENTITIES deprecated с 8.2: используйте отдельные функции; в 8.5 это ещё не универсальное удаление конвертеров.
Рядом: mb_convert_variables, mb_check_encoding, mb_substitute_character. Байты, кодовые точки и графемы; общие правила вызова.
mb_convert_variablesСтарый модуль отдаёт несколько связанных полей в одной кодировке и ожидает, что они будут изменены на месте. mb_convert_variables перекодирует переданные переменные по ссылке. Возвращаемое значение сообщает исходную кодировку; сами новые строки надо читать из тех переменных, которые передали.
PHP 4.0.6+ · mbstring
mb_convert_variables(string $to_encoding, array|string $from_encoding, mixed &$var, mixed &...$vars): string|false- $title и $note содержат байты Windows-1251.
- Вызов получает переменные по ссылке и записывает новые байты внутрь них.
- $source содержит имя Windows-1251; $title теперь читается как Кисть.
| Аргумент / результат | Что передать и получить |
|---|---|
| to_encoding | Кодировка назначения. |
| from_encoding | Обязательное имя/список кандидатов. Старое упоминание пропуска не соответствует современной сигнатуре: аргумент нужен. |
| var, ...vars | Одна или несколько переменных по ссылке: строка, массив, объект. Вложенные строковые значения предполагаются одной исходной кодировки. |
| return | Имя определённой исходной кодировки, а не преобразованный текст; false при неудаче. |
<?php
$title = "\xCA\xE8\xF1\xF2\xFC";
$source = mb_convert_variables('UTF-8', 'Windows-1251', $title);
echo 'Источник: ', $source, "\n";
echo 'Название: ', $title, "\n";
Ожидаемый результат
Источник: Windows-1251
Название: Кисть
Амперсанд & стоит в объявленной сигнатуре функции, в вызове его не пишут. Строковый литерал вместо переменной передать по ссылке нельзя. Если требуется сохранить старый текст отдельной переменной, mb_convert_encoding обычно яснее.
<?php
$product = ['title' => "\xCA\xE8\xF1\xF2\xFC", 'stock' => 12];
$note = "\xCC\xE8\xF0";
mb_convert_variables('UTF-8', 'Windows-1251', $product, $note);
echo $product['title'], ': ', $product['stock'], " шт.\n";
echo 'Примечание: ', $note, "\n";
Ожидаемый результат
Кисть: 12 шт.
Примечание: Мир
Все строковые значения этого пакета имеют одну известную кодировку. Вложенные значения изменены, число stock сохранилось. Функция поддерживает также объекты, но массовое изменение объекта с инвариантами, hooks или readonly-свойствами — другой уровень ответственности; начинайте с простого контейнера данных.
Ошибки и границы. Не смешивайте UTF-8 и Windows-1251 внутри одного пакета: общий детектор не выбирает отдельную таблицу каждой строке. Неизвестные имена — ValueError; выражение вместо переменной по ссылке — ошибка вызова. Следите за алиасами переменных: изменение видно другим ссылкам на те же данные.
Рядом: mb_convert_encoding, mb_detect_encoding, mb_substitute_character. Байты, кодовые точки и графемы; общие правила вызова.
mb_chrВ таблице интеграции символ указан числом Unicode, например 8364 для евро. mb_chr создаёт из такого числа настоящую строку в нужной кодировке. Её можно включить в подпись цены или диагностическое сообщение.
PHP 7.2+ · mbstring
mb_chr(int $codepoint, ?string $encoding = null): string|false- 0x20AC и 8364 — две записи одного числа.
- mb_chr кодирует соответствующий знак как UTF-8.
- Полученная строка € включается в Цена: 25 €.
| Аргумент / результат | Что передать и получить |
|---|---|
| codepoint | Целое Unicode-значение, не номер байта и не строка U+…. Шестнадцатеричная запись 0x20AC — обычное целое. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Строка в выбранной кодировке; false, если значение/символ в ней непредставим. |
<?php
$currency = mb_chr(0x20AC, 'UTF-8');
echo 'Цена: 25 ', $currency, "\n";
echo 'Байтов UTF-8: ', strlen($currency), "\n";
Ожидаемый результат
Цена: 25 €
Байтов UTF-8: 3
Вводится число без кавычек. Результат — строка, а не HTML-сущность. chr создаёт один байт и не является заменой mb_chr для произвольного Unicode.
<?php
$symbol = mb_chr(0x20AC, 'ISO-8859-1');
if ($symbol === false) {
$symbol = 'EUR';
}
echo 'Цена: 25 ', $symbol, "\n";
echo mb_chr(0x110000, 'UTF-8') === false ? "Такой код лежит вне Unicode\n" : "Получен знак\n";
Ожидаемый результат
Цена: 25 EUR
Такой код лежит вне Unicode
В ISO-8859-1 нет евро, поэтому явно выбрано допустимое для задачи обозначение EUR. Нельзя так же произвольно менять имя человека. Один Unicode-код не всегда равен целому видимому emoji: составные последовательности состоят из нескольких кодов.
Ошибки и границы. Неизвестная или неподдерживаемая этой операцией кодировка (например UTF-7) — ValueError; nullable encoding с 8.0. Число кодовой точки не описывает многокомпонентный emoji целиком.
Рядом: mb_ord, mb_convert_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_ordНазвание выглядит нормально, но сравнение не проходит: в начале может стоять не обычный пробел, а NBSP. mb_ord возвращает числовой код первого символа. Это позволяет объяснить различие, которое на экране почти незаметно.
PHP 7.2+ · mbstring
mb_ord(string $string, ?string $encoding = null): int|false- Обычный пробел имеет код U+0020.
- Неразрывный пробел имеет код U+00A0.
- После диагностики выбирают конкретное правило mb_trim для текстового поля.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Непустая строка; читается только первый знак, а не сумма/массив всех кодов. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Целое значение первой Unicode-кодовой точки; false при невозможности декодировать знак. Пустая строка в PHP 8.5 — ValueError. |
<?php
$symbol = '€';
echo 'Unicode: ', mb_ord($symbol, 'UTF-8'), "\n";
echo 'Первый байт: ', ord($symbol[0]), "\n";
Ожидаемый результат
Unicode: 8364
Первый байт: 226
Индекс [0] читает первый байт E2, а mb_ord декодирует целый UTF-8-символ. Поэтому числа различаются. Для нескольких символов нужен явный обход, функция не возвращает массив всех кодов.
<?php
$title = "\u{00A0}Кисть";
printf("Первый знак: U+%04X\n", mb_ord($title, 'UTF-8'));
if (mb_ord($title, 'UTF-8') === 0x00A0) {
echo 'Название после согласованной очистки: ', mb_trim($title, null, 'UTF-8'), "\n";
}
Ожидаемый результат
Первый знак: U+00A0
Название после согласованной очистки: Кисть
printf оформляет число в привычную Unicode-запись. Пример проверяет конкретный случай, а не удаляет все невидимые знаки из любых данных. mb_trim требует PHP 8.4+. В пустой строке нет первого знака: перед вызовом проверяют $title !== ""; в PHP 8.5 пустой вход вызывает ValueError.
Ошибки и границы. Пустая строка, неизвестная или неподдерживаемая этой операцией кодировка — ValueError; nullable encoding с 8.0. Например UTF-7 не является поддерживаемой кодировкой mb_ord. Не используйте результат как визуальную идентичность: один знак может быть последовательностью кодовых точек.
Рядом: mb_chr, mb_trim, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_strcutСтарое устройство принимает подпись максимум в девять байтов, а название хранится в UTF-8. mb_substr ограничивает символы, поэтому здесь нужен mb_strcut: он соблюдает байтовую границу, не оставляя половину многобайтового знака. Обрезка допустима только если это разрешает задача.
PHP 4.0.6+ · mbstring
mb_strcut(string $string, int $start, ?int $length = null, ?string $encoding = null): string- Кисть занимает 10 байтов: по два на каждую букву.
- Бюджет 9 не вмещает последнюю ь целиком.
- mb_strcut возвращает Кист — 8 байтов корректного UTF-8.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Байты текста известной кодировки. |
| start | Байтовое смещение; отрицательное — от конца. Если попало внутрь знака, начало сдвигается к первому байту этого знака. Слишком отрицательное означает начало. |
| length | Байтовый бюджет; null — оставшаяся строка, отрицательное исключает байты с конца. Конечная граница не разрезает знак; результат может быть короче бюджета. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Часть строки в исходной кодировке. |
<?php
$title = 'Кисть';
$wireLabel = mb_strcut($title, 0, 9, 'UTF-8');
echo 'Подпись для устройства: ', $wireLabel, "\n";
echo 'Байтов в подписи: ', strlen($wireLabel), "\n";
echo 'Исходное название: ', $title, "\n";
Ожидаемый результат
Подпись для устройства: Кист
Байтов в подписи: 8
Исходное название: Кисть
Возвращено меньше девяти байтов, поскольку девятый был бы половиной буквы. Если приёмнику нужно полное юридически значимое имя, его не сокращают: сравнивают strlen с пределом и возвращают ошибку. Кодировка протокола должна быть выбрана до применения лимита.
<?php
$text = 'АБВ';
echo 'С байта 0: ', mb_strcut($text, 0, 3, 'UTF-8'), "\n";
echo 'С байта 1: ', mb_strcut($text, 1, 3, 'UTF-8'), "\n";
echo 'С символа 1: ', mb_substr($text, 1, 1, 'UTF-8'), "\n";
Ожидаемый результат
С байта 0: А
С байта 1: А
С символа 1: Б
Байт 1 находится внутри А, поэтому mb_strcut отступает к началу этой буквы. В mb_substr позиция 1 означает уже вторую кодовую точку Б. Эти функции не взаимозаменяемы. Целая кодовая точка всё ещё не гарантирует целую графему с акцентом.
Ошибки и границы. Обработка ошибочных UTF-8/UTF-16 стала последовательнее с 8.4; это не повод принимать повреждённый вход. Неизвестная кодировка — ValueError; nullable encoding с 8.0. Статус «целый знак декодера» не гарантирует целую графему.
Рядом: mb_substr, mb_strimwidth, mb_convert_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_strwidthВ простом текстовом отчёте есть латиница и японские названия. Две кодовые точки могут занимать разные условные ширины: AB считается как 2, 東京 — как 4. mb_strwidth помогает рассчитывать такую колонку, но не измеряет пиксели страницы.
PHP 4.0.6+ · mbstring
mb_strwidth(string $string, ?string $encoding = null): int- AB и 東京 содержат по две кодовые точки.
- В модели восточноазиатской ширины латинские знаки дают по 1, эти иероглифы — по 2.
- До колонки шириной 6 добавляются соответственно 4 и 2 пробела.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Текст для оценки. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Сумма условных единиц: узкие знаки считаются за 1, широкие за 2 по таблицам Unicode расширения. |
<?php
foreach (['AB', '東京'] as $label) {
echo $label, ': кодовых точек ', mb_strlen($label, 'UTF-8');
echo ', условная ширина ', mb_strwidth($label, 'UTF-8'), "\n";
}
Ожидаемый результат
AB: кодовых точек 2, условная ширина 2
東京: кодовых точек 2, условная ширина 4
東京 — японское название Токио. Единицы ширины не равны байтам и не равны CSS-пикселям. На результат отображения влияют шрифт и терминал; emoji, управляющие последовательности и combining marks требуют более сложной модели.
<?php
$stock = ['AB' => 12, '東京' => 8];
foreach ($stock as $location => $quantity) {
$padding = max(0, 6 - mb_strwidth($location, 'UTF-8'));
echo $location, str_repeat(' ', $padding), '| ', $quantity, "\n";
}
Ожидаемый результат
AB | 12
東京 | 8
max не позволяет передать отрицательное число в str_repeat, если название длиннее колонки. Длинную подпись здесь не обрезаем; для ограничения этой же моделью есть mb_strimwidth. На веб-странице для выравнивания колонок применяют CSS или таблицу.
Ошибки и границы. Неизвестная кодировка — ValueError; nullable encoding с 8.0. У функции нет понятия CSS-пикселей и фактически выбранного браузером шрифта; для веб-вёрстки применяют CSS.
Рядом: mb_strimwidth, mb_strlen, mb_str_pad. Байты, кодовые точки и графемы; общие правила вызова.
mb_strimwidthКолонка простого отчёта допускает шесть условных единиц ширины. Длинную подпись нужно сократить и показать две точки. mb_strimwidth учитывает и ширину знаков, и место маркера внутри общего бюджета.
PHP 4.0.6+ · mbstring
mb_strimwidth(string $string, int $start, int $width, string $trim_marker = "", ?string $encoding = null): string- 東京ABCD имеет ширину 8: четыре единицы дают два иероглифа, ещё четыре — ABCD.
- Общий бюджет 6 включает маркер .. шириной 2.
- Остаётся 東京.. шириной 6; короткая 東京 остаётся без маркера.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исходный текст. |
| start | Начальный индекс в символах (не в ширине и не в байтах); отрицательный — от конца. |
| width | Общая допустимая условная ширина результата; отрицательная исторически отсчитывалась от конца, deprecated с 8.3. |
| trim_marker | Добавляется только при обрезке, занимает часть width. Выбирайте маркер не шире бюджета. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Оставшаяся часть с маркером либо без него. |
<?php
foreach (['東京ABCD', '東京'] as $label) {
$short = mb_strimwidth($label, 0, 6, '..', 'UTF-8');
echo $label, ' → ', $short, "\n";
}
Ожидаемый результат
東京ABCD → 東京..
東京 → 東京
start=0 — начало по кодовым точкам, width=6 — предел по условной ширине. Это разные единицы. Две точки появляются только при сокращении и занимают место внутри предела, а не после него.
<?php
foreach (['東京ABCD', 'AB'] as $label) {
$short = mb_strimwidth($label, 0, 6, '..', 'UTF-8');
$padding = 6 - mb_strwidth($short, 'UTF-8');
echo $short, str_repeat(' ', $padding), "| готово\n";
}
Ожидаемый результат
東京..| готово
AB | готово
Первая функция сокращает, вторая измеряет результат в той же модели, str_repeat дополняет пробелами. Для обычной русской карточки по числу кодовых точек чаще нужен mb_substr. Для реального CSS-блока — вёрстка, а не подсчёт условной ширины PHP.
Ошибки и границы. Отрицательные start/width поддержаны с 7.1, отрицательный width deprecated с 8.3. Недопустимый диапазон start/width и неизвестная кодировка — ValueError. Не смешивайте start в символах с width в условных единицах.
Рядом: mb_strwidth, mb_substr, mb_strcut. Байты, кодовые точки и графемы; общие правила вызова.
mb_str_padВ текстовом списке нужно дополнить русское название до восьми кодовых точек, чтобы после него поставить разделитель. Обычная str_pad считает байты; mb_str_pad работает с кодовыми точками и добавляет указанное заполнение слева, справа или с двух сторон.
PHP 8.3+ · mbstring
mb_str_pad(string $string, int $length, string $pad_string = " ", int $pad_type = STR_PAD_RIGHT, ?string $encoding = null): string- Кисть содержит пять кодовых точек.
- До длины 8 не хватает трёх пробелов.
- Получается Кисть и три пробела; полное длинное название не сокращается.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исходный текст. |
| length | Целевая длина в Unicode-кодовых точках; не больше исходной или отрицательная — строка остаётся без дополнения. |
| pad_string | Непустая строка заполнения: повторяется и при необходимости обрезается по символам. |
| pad_type | STR_PAD_RIGHT по умолчанию; STR_PAD_LEFT; STR_PAD_BOTH. При нечётном остатке BOTH добавляет лишний знак справа. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая дополненная строка; не обрезает слишком длинную исходную. |
<?php
echo '[', mb_str_pad('Кисть', 8, ' ', STR_PAD_RIGHT, 'UTF-8'), "]\n";
echo '[', mb_str_pad('Кисть широкая', 8, ' ', STR_PAD_RIGHT, 'UTF-8'), "]\n";
Ожидаемый результат
[Кисть ]
[Кисть широкая]
Скобки показывают добавленные пробелы. length — минимальная общая длина, а не число добавляемых знаков. Длинная строка остаётся целиком. Функция доступна с PHP 8.3 и не заменяет измерение условной ширины или CSS-пикселей.
<?php
echo mb_str_pad('Мир', 8, '.', STR_PAD_LEFT, 'UTF-8'), "\n";
echo mb_str_pad('Мир', 8, '.', STR_PAD_RIGHT, 'UTF-8'), "\n";
echo mb_str_pad('Мир', 8, '.', STR_PAD_BOTH, 'UTF-8'), "\n";
Ожидаемый результат
.....Мир
Мир.....
..Мир...
Всего нужно пять точек. При BOTH нечётный лишний знак оказывается справа. Многосимвольное заполнение повторяется и при необходимости сокращается. Пустое заполнение недопустимо; это ошибка параметра, а не команда «ничего не добавлять».
Ошибки и границы. Пустой pad_string или неизвестный pad_type — ValueError; неверная кодировка — ValueError. Большой length создаёт большую строку: ограничивайте значения из внешней конфигурации.
Рядом: mb_strwidth, mb_strimwidth, mb_strlen. Байты, кодовые точки и графемы; общие правила вызова.
mb_str_splitДля подсказки в учебной игре или диагностики текста нужно пройти по отдельным буквам русского слова. mb_str_split создаёт массив групп кодовых точек. Он не ищет разделитель, как explode: размер каждой группы задаётся числом.
PHP 7.4+ · mbstring
mb_str_split(string $string, int $length = 1, ?string $encoding = null): array- Кисть — одна строка.
- mb_str_split с length=1 создаёт элементы К, и, с, т, ь.
- foreach может показать каждую подсказку вместе с её номером.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Текст для разбиения. |
| length | Положительное число символов в группе; последняя группа может быть короче. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Массив строк; пустой вход даёт пустой массив в современном PHP. |
<?php
$letters = mb_str_split('Кисть', 1, 'UTF-8');
echo 'Первая буква: ', $letters[0], "\n";
echo 'Все буквы: ', implode(' | ', $letters), "\n";
Ожидаемый результат
Первая буква: К
Все буквы: К | и | с | т | ь
Ключ первого элемента — 0. Вертикальные черты добавила implode, а не mb_str_split. Для большого файла массив на каждую кодовую точку потребует много памяти; не делите так весь импорт без необходимости.
<?php
$groups = mb_str_split('АБВГД', 2, 'UTF-8');
foreach ($groups as $index => $group) {
echo 'Группа ', $index + 1, ': ', $group, "\n";
}
Ожидаемый результат
Группа 1: АБ
Группа 2: ВГ
Группа 3: Д
Каждая группа содержит не более двух кодовых точек. Последняя Д не теряется. Для соединённых emoji или буквы с отдельным акцентом такой разбор может разделить видимый знак; графемное разбиение относится к intl.
Ошибки и границы. length < 1 — ValueError; неверная кодировка — ValueError. С 8.0 функция больше не возвращает false при ошибке, encoding nullable. Массив на каждый знак расходует память: не делите так весь многогигабайтный файл.
Рядом: mb_substr, mb_ord, mb_strlen. Байты, кодовые точки и графемы; общие правила вызова.
mb_trimПосле копирования названия из документа вокруг слова остаются неразрывные пробелы. mb_trim убирает выбранные знаки с обоих краёв, сохраняя содержимое поля. Сначала увидим границы строки в квадратных скобках, затем подготовим название для карточки товара. Это осмысленная обработка текстового поля; пароли и подписанные данные так менять нельзя.
PHP 8.4+ · mbstring
mb_trim(string $string, ?string $characters = null, ?string $encoding = null): string- Вход содержит NBSP, слово Кисть и ещё один NBSP.
- mb_trim идёт с обоих краёв, пока встречает разрешённые для удаления знаки.
- Возвращается новая строка; пробелы между словами не исчезают.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исходный текст. |
| characters | null — стандартный набор; строка — буквальный набор отдельных удаляемых символов, а не regex и не диапазон a..z. Пустая строка ничего не удаляет. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка с удалением с обоих краёв до первого знака вне набора. |
По умолчанию удаляются U+0000, U+0009–U+000D, U+0020, U+0085, U+00A0, U+1680, U+180E, U+2000–U+200A, U+2028–U+2029, U+202F, U+205F, U+3000. Это точный набор PHP, а не любое «невидимое»: U+200B и BOM U+FEFF в него не входят.
<?php
$raw = "\u{00A0}Кисть\u{00A0}";
$title = mb_trim($raw, null, 'UTF-8');
echo '[', $title, "]\n";
echo 'Кодовых точек: ', mb_strlen($title, 'UTF-8'), "\n";
Ожидаемый результат
[Кисть]
Кодовых точек: 5
Запись \u{00A0} создаёт неразрывный пробел: он похож на обычный, но имеет другой код. null выбирает стандартный набор пробельных знаков. Квадратные скобки — наша подсказка для чтения вывода, они не часть результата функции. Полный набор знаков приведён перед примерами.
<?php
$raw = "\u{00A0}Кисть широкая\u{00A0}";
$title = mb_trim($raw, null, 'UTF-8');
echo 'Название: [', $title, "]\n";
echo 'Оригинал сохранён: ', mb_strlen($raw, 'UTF-8'), " знаков\n";
Ожидаемый результат
Название: [Кисть широкая]
Оригинал сохранён: 15 знаков
Внутренний пробел нужен для названия из двух слов и остаётся на месте. Выбранная функция работает с обоих краёв. Если надо снять оба края, используйте mb_trim. В форме до такого вызова отдельно убеждаются, что значение — строка корректного UTF-8; массив вместо текста не обрабатывают как название.
<?php
echo '[', mb_trim('《Кисть》', '《》', 'UTF-8'), "]\n";
echo '[', mb_trim(' Кисть ', null, 'UTF-8'), "]\n";
Ожидаемый результат
[Кисть]
[Кисть]
Второй аргумент — набор отдельных знаков, а не точная фраза и не регулярное выражение. Функция снимает сколько угодно крайних знаков из набора до первого другого символа. Для удаления ровно одного известного префикса сначала проверяют его и берут подстроку.
Ошибки и границы. Неизвестная кодировка — ValueError. Функция не удаляет пробелы внутри, не нормализует Unicode и не экранирует HTML. Сначала проверьте исходные байты; не применяйте очистку к бинарным данным.
Рядом: mb_ltrim, mb_rtrim, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_ltrimПосле копирования названия из документа вокруг слова остаются неразрывные пробелы. mb_ltrim убирает выбранные знаки слева, сохраняя содержимое поля. Сначала увидим границы строки в квадратных скобках, затем подготовим название для карточки товара. Это осмысленная обработка текстового поля; пароли и подписанные данные так менять нельзя.
PHP 8.4+ · mbstring
mb_ltrim(string $string, ?string $characters = null, ?string $encoding = null): string- Вход содержит NBSP, слово Кисть и ещё один NBSP.
- mb_ltrim идёт слева, пока встречает разрешённые для удаления знаки.
- Возвращается новая строка; пробелы между словами не исчезают.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исходный текст. |
| characters | null — стандартный набор; строка — буквальный набор отдельных удаляемых символов, а не regex и не диапазон a..z. Пустая строка ничего не удаляет. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка с удалением только слева до первого знака вне набора. |
По умолчанию удаляются U+0000, U+0009–U+000D, U+0020, U+0085, U+00A0, U+1680, U+180E, U+2000–U+200A, U+2028–U+2029, U+202F, U+205F, U+3000. Это точный набор PHP, а не любое «невидимое»: U+200B и BOM U+FEFF в него не входят.
<?php
$raw = "\u{00A0}Кисть\u{00A0}";
$title = mb_ltrim($raw, null, 'UTF-8');
echo '[', $title, "]\n";
echo 'Кодовых точек: ', mb_strlen($title, 'UTF-8'), "\n";
Ожидаемый результат
[Кисть ]
Кодовых точек: 6
Запись \u{00A0} создаёт неразрывный пробел: он похож на обычный, но имеет другой код. null выбирает стандартный набор пробельных знаков. Квадратные скобки — наша подсказка для чтения вывода, они не часть результата функции. Полный набор знаков приведён перед примерами.
<?php
$raw = "\u{00A0}Кисть широкая\u{00A0}";
$title = mb_ltrim($raw, null, 'UTF-8');
echo 'Название: [', $title, "]\n";
echo 'Оригинал сохранён: ', mb_strlen($raw, 'UTF-8'), " знаков\n";
Ожидаемый результат
Название: [Кисть широкая ]
Оригинал сохранён: 15 знаков
Внутренний пробел нужен для названия из двух слов и остаётся на месте. Выбранная функция работает слева. Если надо снять оба края, используйте mb_trim. В форме до такого вызова отдельно убеждаются, что значение — строка корректного UTF-8; массив вместо текста не обрабатывают как название.
<?php
echo '[', mb_ltrim('《Кисть》', '《》', 'UTF-8'), "]\n";
echo '[', mb_ltrim(' Кисть ', null, 'UTF-8'), "]\n";
Ожидаемый результат
[Кисть》]
[Кисть ]
Второй аргумент — набор отдельных знаков, а не точная фраза и не регулярное выражение. Функция снимает сколько угодно крайних знаков из набора до первого другого символа. Для удаления ровно одного известного префикса сначала проверяют его и берут подстроку.
Ошибки и границы. Неизвестная кодировка — ValueError. Функция не удаляет пробелы внутри, не нормализует Unicode и не экранирует HTML. Сначала проверьте исходные байты; не применяйте очистку к бинарным данным.
Рядом: mb_trim, mb_rtrim, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_rtrimПосле копирования названия из документа вокруг слова остаются неразрывные пробелы. mb_rtrim убирает выбранные знаки справа, сохраняя содержимое поля. Сначала увидим границы строки в квадратных скобках, затем подготовим название для карточки товара. Это осмысленная обработка текстового поля; пароли и подписанные данные так менять нельзя.
PHP 8.4+ · mbstring
mb_rtrim(string $string, ?string $characters = null, ?string $encoding = null): string- Вход содержит NBSP, слово Кисть и ещё один NBSP.
- mb_rtrim идёт справа, пока встречает разрешённые для удаления знаки.
- Возвращается новая строка; пробелы между словами не исчезают.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исходный текст. |
| characters | null — стандартный набор; строка — буквальный набор отдельных удаляемых символов, а не regex и не диапазон a..z. Пустая строка ничего не удаляет. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка с удалением только справа до первого знака вне набора. |
По умолчанию удаляются U+0000, U+0009–U+000D, U+0020, U+0085, U+00A0, U+1680, U+180E, U+2000–U+200A, U+2028–U+2029, U+202F, U+205F, U+3000. Это точный набор PHP, а не любое «невидимое»: U+200B и BOM U+FEFF в него не входят.
<?php
$raw = "\u{00A0}Кисть\u{00A0}";
$title = mb_rtrim($raw, null, 'UTF-8');
echo '[', $title, "]\n";
echo 'Кодовых точек: ', mb_strlen($title, 'UTF-8'), "\n";
Ожидаемый результат
[ Кисть]
Кодовых точек: 6
Запись \u{00A0} создаёт неразрывный пробел: он похож на обычный, но имеет другой код. null выбирает стандартный набор пробельных знаков. Квадратные скобки — наша подсказка для чтения вывода, они не часть результата функции. Полный набор знаков приведён перед примерами.
<?php
$raw = "\u{00A0}Кисть широкая\u{00A0}";
$title = mb_rtrim($raw, null, 'UTF-8');
echo 'Название: [', $title, "]\n";
echo 'Оригинал сохранён: ', mb_strlen($raw, 'UTF-8'), " знаков\n";
Ожидаемый результат
Название: [ Кисть широкая]
Оригинал сохранён: 15 знаков
Внутренний пробел нужен для названия из двух слов и остаётся на месте. Выбранная функция работает справа. Если надо снять оба края, используйте mb_trim. В форме до такого вызова отдельно убеждаются, что значение — строка корректного UTF-8; массив вместо текста не обрабатывают как название.
<?php
echo '[', mb_rtrim('《Кисть》', '《》', 'UTF-8'), "]\n";
echo '[', mb_rtrim(' Кисть ', null, 'UTF-8'), "]\n";
Ожидаемый результат
[《Кисть]
[ Кисть]
Второй аргумент — набор отдельных знаков, а не точная фраза и не регулярное выражение. Функция снимает сколько угодно крайних знаков из набора до первого другого символа. Для удаления ровно одного известного префикса сначала проверяют его и берут подстроку.
Ошибки и границы. Неизвестная кодировка — ValueError. Функция не удаляет пробелы внутри, не нормализует Unicode и не экранирует HTML. Сначала проверьте исходные байты; не применяйте очистку к бинарным данным.
Рядом: mb_trim, mb_ltrim, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_strtoupperНужно напечатать крупную подпись на складской этикетке: «Кисть» превращается в «КИСТЬ». При этом некоторые Unicode-буквы разворачиваются в несколько букв, поэтому размер готовой подписи проверяют после преобразования.
PHP 4.3+ · mbstring
mb_strtoupper(string $string, ?string $encoding = null): string- Исходное имя Кисть хранится для обычной карточки.
- mb_strtoupper создаёт копию КИСТЬ для этикетки.
- Ограничение места применяется к полученной копии.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Текст; преобразование — верхний регистр. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка той же кодировки. Unicode-отображение может изменить число кодовых точек/байтов. |
<?php
$title = 'Кисть';
$label = mb_strtoupper($title, 'UTF-8');
echo 'Этикетка: ', $label, "\n";
echo 'Каталог: ', $title, "\n";
Ожидаемый результат
Этикетка: КИСТЬ
Каталог: Кисть
Второй аргумент — кодировка, а не язык. Преобразование выполняет правила Unicode; оно не меняет исходное имя и не транслитерирует его в латиницу.
<?php
$name = 'Straße';
$label = mb_strtoupper($name, 'UTF-8');
echo $name, ' -> ', $label, "\n";
echo mb_strlen($name, 'UTF-8'), ' -> ', mb_strlen($label, 'UTF-8'), " знаков\n";
if (mb_strlen($label, 'UTF-8') > 6) {
echo "Этикетка не помещается в поле из 6 знаков\n";
}
Ожидаемый результат
Straße -> STRASSE
6 -> 7 знаков
Этикетка не помещается в поле из 6 знаков
ß в полном верхнем регистре становится SS. Поэтому правило «вход помещался, значит выход тоже» неверно. Код показывает отказ до отправки; никакого реального принтера здесь нет. Для юридического имени или бренда сохраняют утверждённое написание.
Ошибки и границы. Неизвестная кодировка — ValueError. Преобразование основано на Unicode, не на setlocale; турецкие языковые правила и красивое написание имени человека не гарантируются.
Рядом: mb_convert_case, mb_strtolower, mb_lcfirst. Байты, кодовые точки и графемы; общие правила вызова.
mb_lcfirstЕсть готовая подпись «Заказ готов», которую надо включить после слова «Статус:». mb_lcfirst делает строчной только первую кодовую точку: остальное написание остаётся как было. Это удобно для заранее подготовленных фраз, но не является редактором произвольного текста.
PHP 8.4+ · mbstring
mb_lcfirst(string $string, ?string $encoding = null): string- Заказ готов — отдельная подпись.
- Первая З → з, остальные знаки не меняются.
- В сообщении получается Статус: заказ готов.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Текст; преобразование — нижний регистр первого знака. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка той же кодировки. Unicode-отображение может изменить число кодовых точек/байтов. |
<?php
echo mb_lcfirst('ЗаКАЗ', 'UTF-8'), "\n";
echo mb_strtolower('ЗаКАЗ', 'UTF-8'), "\n";
Ожидаемый результат
заКАЗ
заказ
Первый результат сохраняет КАЗ. Второй меняет все буквы. Выбирайте функцию по тому, какую часть подписи действительно нужно преобразовать.
<?php
$statusLabel = 'Заказ готов';
echo 'Статус: ', mb_lcfirst($statusLabel, 'UTF-8'), ".\n";
echo 'Заголовок: ', $statusLabel, "\n";
Ожидаемый результат
Статус: заказ готов.
Заголовок: Заказ готов
Такое правило подходит для контролируемого набора статусов. Не применяйте его автоматически к именам людей или брендам. mb_lcfirst появилась в PHP 8.4; на старой версии этот вызов отсутствует.
Ошибки и границы. Неизвестная кодировка — ValueError. Преобразование основано на Unicode, не на setlocale; турецкие языковые правила и красивое написание имени человека не гарантируются.
Рядом: mb_convert_case, mb_strtolower, mb_strtoupper. Байты, кодовые точки и графемы; общие правила вызова.
mb_ucfirstСоставленная подпись начинается со строчной буквы: «заказ готов». mb_ucfirst переводит первый знак в начальную форму регистра, сохраняя остальную строку. Для русской буквы это привычная заглавная; для некоторых Unicode-диграфов начальная и полностью верхняя формы различаются.
PHP 8.4+ · mbstring
mb_ucfirst(string $string, ?string $encoding = null): string- заказ готов → Заказ готов.
- Изменяется первая кодовая точка, а не каждое слово.
- Готовую подпись можно использовать в заголовке уведомления.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Текст; преобразование — title case первого знака. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Новая строка той же кодировки. Unicode-отображение может изменить число кодовых точек/байтов. |
<?php
$message = 'заказ готов';
echo mb_ucfirst($message, 'UTF-8'), "\n";
echo mb_ucfirst('заКАЗ готов', 'UTF-8'), "\n";
Ожидаемый результат
Заказ готов
ЗаКАЗ готов
Во втором случае остальной неправильный регистр не исправился. Функция не понимает грамматику и не ищет первое слово после ведущего пробела: первый знак должен быть тем, который требуется изменить.
<?php
echo mb_ucfirst('dzabc', 'UTF-8'), "\n";
echo mb_strtoupper('dzabc', 'UTF-8'), "\n";
Ожидаемый результат
Dzabc
DZABC
У диграфа dz есть начальная форма Dz и верхняя DZ. Это демонстрация реального Unicode-правила, а не обещание автоматически красиво оформить любое имя. Для слов есть MB_CASE_TITLE; оно тоже требует редакционной проверки.
Ошибки и границы. Неизвестная кодировка — ValueError. Преобразование основано на Unicode, не на setlocale; турецкие языковые правила и красивое написание имени человека не гарантируются.
Рядом: mb_convert_case, mb_strtolower, mb_strtoupper. Байты, кодовые точки и графемы; общие правила вызова.
mb_convert_caseУ преобразования регистра несколько разных задач: вывести заголовок, подготовить этикетку или сравнить два написания без регистра. mb_convert_case позволяет явно выбрать правило. Для сравнения Straße и STRASSE нужен полный case folding, а не простое приведение к строчным буквам.
PHP 4.3+ · mbstring
mb_convert_case(string $string, int $mode, ?string $encoding = null): string- Straße и STRASSE имеют разное исходное написание.
- MB_CASE_FOLD даёт strasse в обоих случаях.
- Сравниваем ключи; пользователю показываем сохранённое исходное название.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Исходный текст. |
| mode | Одна из восьми MB_CASE_* констант: UPPER, LOWER, TITLE, FOLD и их *_SIMPLE варианты. Это выбор одного режима, не битовая маска. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Строка в исходной кодировке после Unicode-преобразования. |
<?php
$text = 'новый ЗАКАЗ';
echo mb_convert_case($text, MB_CASE_LOWER, 'UTF-8'), "\n";
echo mb_convert_case($text, MB_CASE_UPPER, 'UTF-8'), "\n";
echo mb_convert_case($text, MB_CASE_TITLE, 'UTF-8'), "\n";
Ожидаемый результат
новый заказ
НОВЫЙ ЗАКАЗ
Новый Заказ
Второй аргумент — одна константа выбора. MB_CASE_TITLE меняет форму слов; это не гарантия правильного написания аббревиатур и фамилий. Все восемь режимов описаны в параметрах выше.
<?php
$stored = 'Straße';
$imported = 'STRASSE';
$left = mb_convert_case($stored, MB_CASE_FOLD, 'UTF-8');
$right = mb_convert_case($imported, MB_CASE_FOLD, 'UTF-8');
echo 'Ключи: ', $left, ' / ', $right, "\n";
if ($left === $right) {
echo 'Найдено сохранённое название: ', $stored, "\n";
}
Ожидаемый результат
Ключи: strasse / strasse
Найдено сохранённое название: Straße
Здесь прикладное правило разрешает такое сопоставление; для уникальных идентификаторов его заранее согласуют. Case folding не включает каноническую нормализацию Unicode и не обязан совпадать с правилами базы данных.
<?php
echo mb_convert_case('Straße', MB_CASE_FOLD, 'UTF-8'), "\n";
echo mb_convert_case('Straße', MB_CASE_FOLD_SIMPLE, 'UTF-8'), "\n";
Ожидаемый результат
strasse
straße
SIMPLE не разворачивает ß в ss. Он нужен там, где выбран именно такой контракт, а не как более быстрая взаимозаменяемая версия. Пример показывает причину возможного несовпадения поиска.
Ошибки и границы. Неизвестный mode/encoding — ValueError. FOLD и SIMPLE добавлены в 7.3. С 8.3 условное правило греческого sigma действует для LOWER/TITLE, но не LOWER_SIMPLE/TITLE_SIMPLE. Регистр не зависит от locale; Unicode-таблицы меняются между версиями PHP.
Рядом: mb_strtolower, mb_strtoupper, mb_ucfirst. Байты, кодовые точки и графемы; общие правила вызова.
mb_convert_kanaЯпонский поставщик прислал артикул широкими символами AB12, а каталог хранит AB12. mb_convert_kana умеет согласованно менять ширину выбранных знаков и формы kana. Это помогает сопоставить данные по заранее выбранному правилу, сохраняя исходное написание.
PHP 4.0.6+ · mbstring
mb_convert_kana(string $string, string $mode = "KV", ?string $encoding = null): string- В исходнике AB12 CD широкие латинские знаки, цифры и пробел.
- Флаги as выбирают узкие ASCII-формы и обычный пробел.
- Результат AB12 CD можно использовать в согласованном поисковом ключе.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Японский текст, широкая латиница/цифры или пробелы, к которым применимы флаги. |
| mode | Комбинация совместимых букв; по умолчанию KV. Каждая буква выбирает отдельное направление. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Преобразованная строка. Число кодовых точек может измениться при объединении озвончения. |
| Флаги | Направление |
|---|---|
| r / R | Широкая → узкая / узкая → широкая латиница |
| n / N | Широкие → узкие / узкие → широкие цифры |
| a / A | Широкие → узкие / обратное для набора ASCII U+0021–U+007E, кроме кавычек U+0022/U+0027, обратной косой U+005C и тильды U+007E |
| s / S | U+3000 → обычный пробел / обратное |
| k / K | Широкая катакана → узкая / обратное |
| h / H | Широкая хирагана → узкая катакана / узкая катакана → широкая хирагана |
| c / C | Широкая катакана → хирагана / обратное |
| V | Объединить знак озвончения с предыдущим знаком; используют с K или H |
<?php
$raw = 'AB12 CD';
$code = mb_convert_kana($raw, 'as', 'UTF-8');
echo 'Источник: ', $raw, "\n";
echo 'Для сопоставления: ', $code, "\n";
Ожидаемый результат
Источник: AB12 CD
Для сопоставления: AB12 CD
Флаг a меняет поддерживаемые широкие ASCII-знаки, s — широкий пробел. Это не общая очистка строки и не транслитерация. Полный перечень флагов и исключения сохранены в таблице выше.
<?php
$catalog = ['AB12' => 'Кисть'];
$received = 'AB12';
$key = mb_convert_kana($received, 'a', 'UTF-8');
if (array_key_exists($key, $catalog)) {
echo 'Получено ', $received, '; найден ', $key, ': ', $catalog[$key], "\n";
}
Ожидаемый результат
Получено AB12; найден AB12: Кисть
Такое сопоставление допустимо, только если правило поставщика считает эти формы одним артикулом. Два разных внешних идентификатора могут превратиться в один ключ — коллизии нужно обнаруживать. Исходное значение остаётся для отчёта.
<?php
$half = 'ガク';
$full = mb_convert_kana($half, 'KV', 'UTF-8');
echo $half, ' -> ', $full, "\n";
echo 'Кодовых точек: ', mb_strlen($half, 'UTF-8'), ' -> ', mb_strlen($full, 'UTF-8'), "\n";
Ожидаемый результат
ガク -> ガク
Кодовых точек: 3 -> 2
K меняет узкую катакану на широкую, V объединяет озвончение с предыдущим знаком. Поэтому длина изменилась. Валидацию длины делают по форме, которая действительно отправится получателю; юридически значимое имя не переписывают без правила.
Ошибки и границы. С 8.2 конфликтующие флаги, например sS, дают ValueError; неизвестная кодировка также ValueError. Это не транслитерация в латиницу и не универсальная Unicode-нормализация.
Рядом: mb_convert_encoding, mb_strwidth, mb_convert_case. Байты, кодовые точки и графемы; общие правила вызова.
mb_encode_numericentityИногда текстовый формат требует представить выбранные Unicode-знаки числовыми HTML-ссылками. Например, евро можно записать как € или €. Функция создаёт это представление по карте диапазонов; само по себе оно не является универсальным HTML-экранированием.
PHP 4.0.6+ · mbstring
mb_encode_numericentity(string $string, array $map, ?string $encoding = null, bool $hex = false): string- A€ содержит ASCII-букву и знак вне ASCII.
- Карта от U+0080 выбирает только евро.
- A€ — буквальная строка результата; в HTML число обозначает тот же знак €.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Входной текст с символами для кодирования. |
| map | Плоский массив групп по четыре: начало диапазона Unicode, конец включительно, смещение, битовая маска. При кодировании используется (codepoint + offset) & mask; для обычных ссылок offset=0, mask=0x10FFFF. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| hex | false — десятичные ссылки; true — шестнадцатеричные. |
| return | Преобразованная строка; данные вне выбранных диапазонов остаются как были. |
<?php
$map = [0x80, 0x10FFFF, 0, 0x10FFFF];
echo mb_encode_numericentity('A€', $map, 'UTF-8'), "\n";
echo mb_encode_numericentity('A€', $map, 'UTF-8', true), "\n";
Ожидаемый результат
A€
A€
Четыре числа — одна группа: начало, конец, смещение, маска. Начало 0x80 оставляет ASCII без изменения; смещение 0 сохраняет номер Unicode. Последний аргумент true выбирает шестнадцатеричную запись. Это обычные строки, которые здесь показаны буквально.
<?php
$map = [0x80, 0x10FFFF, 0, 0x10FFFF];
$text = '<Кисть>';
echo 'Выбранные знаки: ', mb_encode_numericentity($text, $map, 'UTF-8'), "\n";
echo 'Текст для HTML: ', htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), "\n";
Ожидаемый результат
Выбранные знаки: <Кисть>
Текст для HTML: <Кисть>
У первого результата угловые скобки остались: они вне выбранного диапазона. Для показа пользовательского текста в HTML обычно нужен второй вариант. Для JavaScript, URL и SQL правила другие; не пытайтесь одной картой решить все контексты.
Ошибки и границы. Количество элементов map должно делиться на четыре, иначе ValueError. С 8.4 непереводимые в int значения карты вызывают ValueError; допустимы int и неявно преобразуемые float/bool/null/числовые строки, но для ясности используйте целые. Неверная кодировка — ValueError; nullable encoding с 8.0. Именованные сущности вроде & не входят в задачу числового декодера; для их набора есть html_entity_decode.
Рядом: mb_decode_numericentity, mb_chr, mb_ord. Байты, кодовые точки и графемы; общие правила вызова.
mb_decode_numericentityПартнёр передал знак евро в виде числовой HTML-ссылки, а отчёту нужна обычная UTF-8-строка. mb_decode_numericentity раскрывает ссылки только в выбранных диапазонах. После декодирования строка остаётся внешними данными и требует правил своего назначения.
PHP 4.0.6+ · mbstring
mb_decode_numericentity(string $string, array $map, ?string $encoding = null): string- В A€ евро пока записан последовательностью ASCII-знаков.
- Карта разрешает числовой код евро.
- Результат A€ — обычный текст с настоящим знаком валюты.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Входной текст с десятичными/шестнадцатеричными числовыми ссылками. |
| map | Плоский массив групп по четыре: начало диапазона Unicode, конец включительно, смещение, битовая маска. При кодировании используется (codepoint + offset) & mask; для обычных ссылок offset=0, mask=0x10FFFF. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Преобразованная строка; данные вне выбранных диапазонов остаются как были. |
<?php
$map = [0x80, 0x10FFFF, 0, 0x10FFFF];
echo mb_decode_numericentity('Цена: 5 €', $map, 'UTF-8'), "\n";
echo mb_decode_numericentity('Цена: 5 €', $map, 'UTF-8'), "\n";
Ожидаемый результат
Цена: 5 €
Цена: 5 €
Десятичная и шестнадцатеричная записи дали один знак. Карта состоит из групп по четыре числа. Именованная & — другая форма: для общего набора HTML-сущностей смотрят html_entity_decode.
<?php
$map = [0, 0x10FFFF, 0, 0x10FFFF];
$text = mb_decode_numericentity('<b>Кисть</b>', $map, 'UTF-8');
echo 'Полученные данные: ', $text, "\n";
echo 'Безопасный HTML-текст: ', htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), "\n";
Ожидаемый результат
Полученные данные: <b>Кисть</b>
Безопасный HTML-текст: <b>Кисть</b>
В CLI первая строка просто текст; если без экранирования поместить её в HTML, браузер воспримет тег. Поэтому декодирование и вывод — отдельные действия. Кавычки, теги и произвольные атрибуты нельзя объявлять доверенными после успешного преобразования.
Ошибки и границы. Количество элементов map должно делиться на четыре, иначе ValueError. С 8.4 непереводимые в int значения карты вызывают ValueError; допустимы int и неявно преобразуемые float/bool/null/числовые строки, но для ясности используйте целые. Неверная кодировка — ValueError; nullable encoding с 8.0. Именованные сущности вроде & не входят в задачу числового декодера; для их набора есть html_entity_decode.
Рядом: mb_encode_numericentity, mb_chr, mb_ord. Байты, кодовые точки и графемы; общие правила вызова.
mb_strposВ текстовой заметке нужно найти первое упоминание метки и получить его позицию. mb_strpos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр букв учитывается: Кисть и кисть различаются.
PHP 4.0.6+ · mbstring
mb_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|false- Кисть / Кисть — исходная строка; второе слово начинается с позиции 8.
- mb_strpos выбирает первое совпадение и возвращает 0.
- false означает отсутствие; успешный нулевой индекс нельзя принять за ошибку.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Текст, в котором ищем. |
| needle | Подстрока в той же кодировке, не regex. |
| offset | Начало поиска в кодовых точках с нуля; отрицательный отсчитывается от конца. Возвращаемая позиция остаётся относительно начала всей строки. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Индекс кодовой точки с нуля; false, если совпадения нет. Число 0 — успешное совпадение в начале. |
<?php
$text = 'Кисть / Кисть';
$position = mb_strpos($text, 'Кисть', 0, 'UTF-8');
if ($position !== false) {
echo 'Найдено с позиции ', $position, "
";
echo 'Фрагмент от позиции: ', mb_substr($text, $position, null, 'UTF-8'), "
";
}
Ожидаемый результат
Найдено с позиции 0
Фрагмент от позиции: Кисть / Кисть
Нумерация начинается с нуля. Даже при совпадении в начале условие !== false остаётся истинным. mb_substr принимает позицию в тех же единицах. Обычный substr воспринял бы её как байтовый индекс и мог разрезать русскую букву.
<?php
$comment = 'заказ: принят; заказ: выдан';
$position = mb_strpos($comment, 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "В заметке нет отметки заказа
";
} else {
$note = mb_substr($comment, $position, null, 'UTF-8');
echo 'Выбранная отметка: ', $note, "
";
}
Ожидаемый результат
Выбранная отметка: заказ: принят; заказ: выдан
Первый поиск сохраняет текст от первой отметки, включая последующие записи. Если поставщик допускает произвольный регистр метки, нужен регистронезависимый вариант. Для настоящего структурированного журнала с датами и полями лучше разбирать его формат, а не считать эту подстроку доказательством статуса заказа.
<?php
$position = mb_strpos('Доставка завтра', 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "Метка не найдена: уточните текст заметки
";
}
$emptyNeedle = '';
if ($emptyNeedle === '') {
echo "Введите непустой запрос поиска
";
}
Ожидаемый результат
Метка не найдена: уточните текст заметки
Введите непустой запрос поиска
Пустую строку PHP 8 разрешает как искомую, но для интерфейса поиска это часто лишено смысла. Поэтому правило формы проверяется до вызова. Слишком большой offset является отдельной ошибкой параметра. Регистронезависимость не означает Unicode-нормализацию или языковую коллацию.
Ошибки и границы. С PHP 8 пустой needle разрешён: определите заранее, нужен ли такой поиск вашему полю. Offset за допустимыми границами и неизвестная кодировка — ValueError; nullable encoding с 8.0. Отрицательные offsets добавлены в 7.1. Длина/позиция в символах не является длиной в байтах или графемах.
Рядом: mb_stripos, mb_strrpos, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_striposВ текстовой заметке нужно найти первое упоминание метки и получить его позицию. mb_stripos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр Unicode-букв при поиске не учитывается.
PHP 5.2+ · mbstring
mb_stripos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|false- КИСТЬ / кисть — исходная строка; второе слово начинается с позиции 8.
- mb_stripos выбирает первое совпадение и возвращает 0.
- false означает отсутствие; успешный нулевой индекс нельзя принять за ошибку.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Текст, в котором ищем. |
| needle | Подстрока в той же кодировке, не regex. |
| offset | Начало поиска в кодовых точках с нуля; отрицательный отсчитывается от конца. Возвращаемая позиция остаётся относительно начала всей строки. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Индекс кодовой точки с нуля; false, если совпадения нет. Число 0 — успешное совпадение в начале. |
<?php
$text = 'КИСТЬ / кисть';
$position = mb_stripos($text, 'кисть', 0, 'UTF-8');
if ($position !== false) {
echo 'Найдено с позиции ', $position, "
";
echo 'Фрагмент от позиции: ', mb_substr($text, $position, null, 'UTF-8'), "
";
}
Ожидаемый результат
Найдено с позиции 0
Фрагмент от позиции: КИСТЬ / кисть
Нумерация начинается с нуля. Даже при совпадении в начале условие !== false остаётся истинным. mb_substr принимает позицию в тех же единицах. Обычный substr воспринял бы её как байтовый индекс и мог разрезать русскую букву.
<?php
$comment = 'ЗАКАЗ: принят; заказ: выдан';
$position = mb_stripos($comment, 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "В заметке нет отметки заказа
";
} else {
$note = mb_substr($comment, $position, null, 'UTF-8');
echo 'Выбранная отметка: ', $note, "
";
}
Ожидаемый результат
Выбранная отметка: ЗАКАЗ: принят; заказ: выдан
Первый поиск сохраняет текст от первой отметки, включая последующие записи. Слово ЗАКАЗ находится по запросу заказ, а исходное написание результата сохраняется. Для настоящего структурированного журнала с датами и полями лучше разбирать его формат, а не считать эту подстроку доказательством статуса заказа.
<?php
$position = mb_stripos('Доставка завтра', 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "Метка не найдена: уточните текст заметки
";
}
$emptyNeedle = '';
if ($emptyNeedle === '') {
echo "Введите непустой запрос поиска
";
}
Ожидаемый результат
Метка не найдена: уточните текст заметки
Введите непустой запрос поиска
Пустую строку PHP 8 разрешает как искомую, но для интерфейса поиска это часто лишено смысла. Поэтому правило формы проверяется до вызова. Слишком большой offset является отдельной ошибкой параметра. Регистронезависимость не означает Unicode-нормализацию или языковую коллацию.
Ошибки и границы. С PHP 8 пустой needle разрешён: определите заранее, нужен ли такой поиск вашему полю. Offset за допустимыми границами и неизвестная кодировка — ValueError; nullable encoding с 8.0. Отрицательные offsets добавлены в 7.1. Регистронезависимость не равна языковой коллации/Unicode-нормализации; не рассчитывайте, что любые визуально одинаковые или расширяющиеся формы совпадут. Длина/позиция в символах не является длиной в байтах или графемах.
Рядом: mb_strpos, mb_strrpos, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_strrposВ текстовой заметке нужно найти последнее упоминание метки и получить его позицию. mb_strrpos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр букв учитывается: Кисть и кисть различаются.
PHP 4.0.6+ · mbstring
mb_strrpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|false- Кисть / Кисть — исходная строка; второе слово начинается с позиции 8.
- mb_strrpos выбирает последнее совпадение и возвращает 8.
- false означает отсутствие; успешный нулевой индекс нельзя принять за ошибку.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Текст, в котором ищем. |
| needle | Подстрока в той же кодировке, не regex. |
| offset | При offset ≥ 0 ищет последнее совпадение в части начиная с этой позиции; отрицательный ограничивает правую границу поиска относительно конца. Возвращённая позиция всё равно от начала всей строки. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Индекс кодовой точки с нуля; false, если совпадения нет. Число 0 — успешное совпадение в начале. |
<?php
$text = 'Кисть / Кисть';
$position = mb_strrpos($text, 'Кисть', 0, 'UTF-8');
if ($position !== false) {
echo 'Найдено с позиции ', $position, "
";
echo 'Фрагмент от позиции: ', mb_substr($text, $position, null, 'UTF-8'), "
";
}
Ожидаемый результат
Найдено с позиции 8
Фрагмент от позиции: Кисть
Нумерация начинается с нуля. Даже при совпадении в начале условие !== false остаётся истинным. mb_substr принимает позицию в тех же единицах. Обычный substr воспринял бы её как байтовый индекс и мог разрезать русскую букву.
<?php
$comment = 'заказ: принят; заказ: выдан';
$position = mb_strrpos($comment, 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "В заметке нет отметки заказа
";
} else {
$note = mb_substr($comment, $position, null, 'UTF-8');
echo 'Выбранная отметка: ', $note, "
";
}
Ожидаемый результат
Выбранная отметка: заказ: выдан
Последний поиск позволяет получить последнюю отметку в этом простом текстовом формате. Если поставщик допускает произвольный регистр метки, нужен регистронезависимый вариант. Для настоящего структурированного журнала с датами и полями лучше разбирать его формат, а не считать эту подстроку доказательством статуса заказа.
<?php
$position = mb_strrpos('Доставка завтра', 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "Метка не найдена: уточните текст заметки
";
}
$emptyNeedle = '';
if ($emptyNeedle === '') {
echo "Введите непустой запрос поиска
";
}
Ожидаемый результат
Метка не найдена: уточните текст заметки
Введите непустой запрос поиска
Пустую строку PHP 8 разрешает как искомую, но для интерфейса поиска это часто лишено смысла. Поэтому правило формы проверяется до вызова. Слишком большой offset является отдельной ошибкой параметра. Регистронезависимость не означает Unicode-нормализацию или языковую коллацию.
Ошибки и границы. С PHP 8 пустой needle разрешён: определите заранее, нужен ли такой поиск вашему полю. Offset за допустимыми границами и неизвестная кодировка — ValueError; nullable encoding с 8.0. С 8.0 нельзя передать encoding третьим аргументом вместо offset. Длина/позиция в символах не является длиной в байтах или графемах.
Рядом: mb_strpos, mb_stripos, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_strriposВ текстовой заметке нужно найти последнее упоминание метки и получить его позицию. mb_strripos считает кодовые точки, поэтому ответ можно передать в mb_substr. Регистр Unicode-букв при поиске не учитывается.
PHP 5.2+ · mbstring
mb_strripos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null): int|false- КИСТЬ / кисть — исходная строка; второе слово начинается с позиции 8.
- mb_strripos выбирает последнее совпадение и возвращает 8.
- false означает отсутствие; успешный нулевой индекс нельзя принять за ошибку.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Текст, в котором ищем. |
| needle | Подстрока в той же кодировке, не regex. |
| offset | При offset ≥ 0 ищет последнее совпадение в части начиная с этой позиции; отрицательный ограничивает правую границу поиска относительно конца. Возвращённая позиция всё равно от начала всей строки. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Индекс кодовой точки с нуля; false, если совпадения нет. Число 0 — успешное совпадение в начале. |
<?php
$text = 'КИСТЬ / кисть';
$position = mb_strripos($text, 'кисть', 0, 'UTF-8');
if ($position !== false) {
echo 'Найдено с позиции ', $position, "
";
echo 'Фрагмент от позиции: ', mb_substr($text, $position, null, 'UTF-8'), "
";
}
Ожидаемый результат
Найдено с позиции 8
Фрагмент от позиции: кисть
Нумерация начинается с нуля. Даже при совпадении в начале условие !== false остаётся истинным. mb_substr принимает позицию в тех же единицах. Обычный substr воспринял бы её как байтовый индекс и мог разрезать русскую букву.
<?php
$comment = 'ЗАКАЗ: принят; заказ: выдан';
$position = mb_strripos($comment, 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "В заметке нет отметки заказа
";
} else {
$note = mb_substr($comment, $position, null, 'UTF-8');
echo 'Выбранная отметка: ', $note, "
";
}
Ожидаемый результат
Выбранная отметка: заказ: выдан
Последний поиск позволяет получить последнюю отметку в этом простом текстовом формате. Слово ЗАКАЗ находится по запросу заказ, а исходное написание результата сохраняется. Для настоящего структурированного журнала с датами и полями лучше разбирать его формат, а не считать эту подстроку доказательством статуса заказа.
<?php
$position = mb_strripos('Доставка завтра', 'заказ:', 0, 'UTF-8');
if ($position === false) {
echo "Метка не найдена: уточните текст заметки
";
}
$emptyNeedle = '';
if ($emptyNeedle === '') {
echo "Введите непустой запрос поиска
";
}
Ожидаемый результат
Метка не найдена: уточните текст заметки
Введите непустой запрос поиска
Пустую строку PHP 8 разрешает как искомую, но для интерфейса поиска это часто лишено смысла. Поэтому правило формы проверяется до вызова. Слишком большой offset является отдельной ошибкой параметра. Регистронезависимость не означает Unicode-нормализацию или языковую коллацию.
Ошибки и границы. С PHP 8 пустой needle разрешён: определите заранее, нужен ли такой поиск вашему полю. Offset за допустимыми границами и неизвестная кодировка — ValueError; nullable encoding с 8.0. Регистронезависимость не равна языковой коллации/Unicode-нормализации; не рассчитывайте, что любые визуально одинаковые или расширяющиеся формы совпадут. Длина/позиция в символах не является длиной в байтах или графемах.
Рядом: mb_strpos, mb_stripos, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_strstrВ подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от первого совпадения. mb_strstr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск учитывает регистр букв.
PHP 5.2+ · mbstring
mb_strstr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding = null): string|false- Дом/Склад/Офис — исходная подпись из трёх частей.
- Поиск первого / делит её на Дом и /Склад/Офис.
- before_needle=true выбирает левую часть без разделителя; false — правую вместе с ним.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Исходный текст. |
| needle | Искомая подстрока в той же кодировке. Даже у mb_strrchr/mb_strrichr современный PHP ищет всю переданную подстроку; это не байтовый strrchr с первым знаком. |
| before_needle | false — вернуть от найденного вхождения до конца, включая needle; true — от начала до вхождения, исключая needle. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Часть исходного текста или false. Успешная часть может быть пустой строкой, поэтому используйте === false для отсутствия. |
<?php
$path = 'Дом/Склад/Офис';
echo 'До разделителя: ', mb_strstr($path, '/', true, 'UTF-8'), "
";
echo 'От разделителя: ', mb_strstr($path, '/', false, 'UTF-8'), "
";
Ожидаемый результат
До разделителя: Дом
От разделителя: /Склад/Офис
Третий аргумент задаёт сторону, а не чувствительность к регистру. / входит только в правую часть. Это удобно для собственного простого формата подписи, если / запрещён внутри названий. Функция не разбирает путь файловой системы и не проверяет доступ к каталогу.
<?php
$comment = 'Статус: принят; Статус: выдан';
$part = mb_strstr($comment, 'Статус:', false, 'UTF-8');
echo $part === false ? "Отметка отсутствует
" : 'Найдено: ' . $part . "
";
$missing = mb_strstr($comment, 'Ошибка:', false, 'UTF-8');
if ($missing === false) {
echo "В этой заметке нет метки ошибки
";
}
Ожидаемый результат
Найдено: Статус: принят; Статус: выдан
В этой заметке нет метки ошибки
Результат сохраняет исходные буквы, даже когда поиск не учитывает регистр. false означает, что подстроки не было. Это поиск в известном тексте, а не проверка реального состояния заказа: для работы с API используют структурированные поля ответа.
<?php
$before = mb_strstr('Кисть широкая', 'Кисть', true, 'UTF-8');
if ($before === false) {
echo "Слово не найдено
";
} else {
echo 'Слово найдено. До него: [', $before, "]
";
}
Ожидаемый результат
Слово найдено. До него: []
Метка стоит в начале, поэтому перед ней ничего нет. Это успешный пустой результат, а не false. Проверка if (!$before) смешала бы два разных исхода. В mb_strrchr/mb_strrichr текущего PHP искомая строка используется целиком; поведение нельзя переносить с байтовой strrchr.
Ошибки и границы. Пустой needle разрешён с 8.0; для такой границы возможен пустой успешный результат. Неизвестная кодировка — ValueError, nullable encoding с 8.0. С 8.3.2 before_needle=true для повреждённых/SJIS-mac строк согласован с общими индексами. Не разрезает графемы по их визуальному смыслу и не выполняет HTML-экранирование.
Рядом: mb_stristr, mb_strrchr, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_stristrВ подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от первого совпадения. mb_stristr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск не зависит от регистра Unicode-букв.
PHP 5.2+ · mbstring
mb_stristr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding = null): string|false- Дом/Склад/Офис — исходная подпись из трёх частей.
- Поиск первого / делит её на Дом и /Склад/Офис.
- before_needle=true выбирает левую часть без разделителя; false — правую вместе с ним.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Исходный текст. |
| needle | Искомая подстрока в той же кодировке. Даже у mb_strrchr/mb_strrichr современный PHP ищет всю переданную подстроку; это не байтовый strrchr с первым знаком. |
| before_needle | false — вернуть от найденного вхождения до конца, включая needle; true — от начала до вхождения, исключая needle. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Часть исходного текста или false. Успешная часть может быть пустой строкой, поэтому используйте === false для отсутствия. |
<?php
$path = 'Дом/Склад/Офис';
echo 'До разделителя: ', mb_stristr($path, '/', true, 'UTF-8'), "
";
echo 'От разделителя: ', mb_stristr($path, '/', false, 'UTF-8'), "
";
Ожидаемый результат
До разделителя: Дом
От разделителя: /Склад/Офис
Третий аргумент задаёт сторону, а не чувствительность к регистру. / входит только в правую часть. Это удобно для собственного простого формата подписи, если / запрещён внутри названий. Функция не разбирает путь файловой системы и не проверяет доступ к каталогу.
<?php
$comment = 'Статус: принят; СТАТУС: выдан';
$part = mb_stristr($comment, 'статус:', false, 'UTF-8');
echo $part === false ? "Отметка отсутствует
" : 'Найдено: ' . $part . "
";
$missing = mb_stristr($comment, 'Ошибка:', false, 'UTF-8');
if ($missing === false) {
echo "В этой заметке нет метки ошибки
";
}
Ожидаемый результат
Найдено: Статус: принят; СТАТУС: выдан
В этой заметке нет метки ошибки
Результат сохраняет исходные буквы, даже когда поиск не учитывает регистр. false означает, что подстроки не было. Это поиск в известном тексте, а не проверка реального состояния заказа: для работы с API используют структурированные поля ответа.
<?php
$before = mb_stristr('Кисть широкая', 'Кисть', true, 'UTF-8');
if ($before === false) {
echo "Слово не найдено
";
} else {
echo 'Слово найдено. До него: [', $before, "]
";
}
Ожидаемый результат
Слово найдено. До него: []
Метка стоит в начале, поэтому перед ней ничего нет. Это успешный пустой результат, а не false. Проверка if (!$before) смешала бы два разных исхода. В mb_strrchr/mb_strrichr текущего PHP искомая строка используется целиком; поведение нельзя переносить с байтовой strrchr.
Ошибки и границы. Пустой needle разрешён с 8.0; для такой границы возможен пустой успешный результат. Неизвестная кодировка — ValueError, nullable encoding с 8.0. Не разрезает графемы по их визуальному смыслу и не выполняет HTML-экранирование.
Рядом: mb_strstr, mb_strrchr, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_strrchrВ подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от последнего совпадения. mb_strrchr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск учитывает регистр букв.
PHP 5.2+ · mbstring
mb_strrchr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding = null): string|false- Дом/Склад/Офис — исходная подпись из трёх частей.
- Поиск последнего / делит её на Дом/Склад и /Офис.
- before_needle=true выбирает левую часть без разделителя; false — правую вместе с ним.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Исходный текст. |
| needle | Искомая подстрока в той же кодировке. Даже у mb_strrchr/mb_strrichr современный PHP ищет всю переданную подстроку; это не байтовый strrchr с первым знаком. |
| before_needle | false — вернуть от найденного вхождения до конца, включая needle; true — от начала до вхождения, исключая needle. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Часть исходного текста или false. Успешная часть может быть пустой строкой, поэтому используйте === false для отсутствия. |
<?php
$path = 'Дом/Склад/Офис';
echo 'До разделителя: ', mb_strrchr($path, '/', true, 'UTF-8'), "
";
echo 'От разделителя: ', mb_strrchr($path, '/', false, 'UTF-8'), "
";
Ожидаемый результат
До разделителя: Дом/Склад
От разделителя: /Офис
Третий аргумент задаёт сторону, а не чувствительность к регистру. / входит только в правую часть. Это удобно для собственного простого формата подписи, если / запрещён внутри названий. Функция не разбирает путь файловой системы и не проверяет доступ к каталогу.
<?php
$comment = 'Статус: принят; Статус: выдан';
$part = mb_strrchr($comment, 'Статус:', false, 'UTF-8');
echo $part === false ? "Отметка отсутствует
" : 'Найдено: ' . $part . "
";
$missing = mb_strrchr($comment, 'Ошибка:', false, 'UTF-8');
if ($missing === false) {
echo "В этой заметке нет метки ошибки
";
}
Ожидаемый результат
Найдено: Статус: выдан
В этой заметке нет метки ошибки
Результат сохраняет исходные буквы, даже когда поиск не учитывает регистр. false означает, что подстроки не было. Это поиск в известном тексте, а не проверка реального состояния заказа: для работы с API используют структурированные поля ответа.
<?php
$before = mb_strrchr('Кисть широкая', 'Кисть', true, 'UTF-8');
if ($before === false) {
echo "Слово не найдено
";
} else {
echo 'Слово найдено. До него: [', $before, "]
";
}
Ожидаемый результат
Слово найдено. До него: []
Метка стоит в начале, поэтому перед ней ничего нет. Это успешный пустой результат, а не false. Проверка if (!$before) смешала бы два разных исхода. В mb_strrchr/mb_strrichr текущего PHP искомая строка используется целиком; поведение нельзя переносить с байтовой strrchr.
Ошибки и границы. Пустой needle разрешён с 8.0; для такой границы возможен пустой успешный результат. Неизвестная кодировка — ValueError, nullable encoding с 8.0. Не разрезает графемы по их визуальному смыслу и не выполняет HTML-экранирование.
Рядом: mb_strstr, mb_stristr, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_strrichrВ подписи категории или простой служебной заметке нужно сразу получить часть текста до либо от последнего совпадения. mb_strrichr возвращает сам фрагмент, поэтому отдельное вычисление позиции не требуется. Поиск не зависит от регистра Unicode-букв.
PHP 5.2+ · mbstring
mb_strrichr(string $haystack, string $needle, bool $before_needle = false, ?string $encoding = null): string|false- Дом/Склад/Офис — исходная подпись из трёх частей.
- Поиск последнего / делит её на Дом/Склад и /Офис.
- before_needle=true выбирает левую часть без разделителя; false — правую вместе с ним.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Исходный текст. |
| needle | Искомая подстрока в той же кодировке. Даже у mb_strrchr/mb_strrichr современный PHP ищет всю переданную подстроку; это не байтовый strrchr с первым знаком. |
| before_needle | false — вернуть от найденного вхождения до конца, включая needle; true — от начала до вхождения, исключая needle. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Часть исходного текста или false. Успешная часть может быть пустой строкой, поэтому используйте === false для отсутствия. |
<?php
$path = 'Дом/Склад/Офис';
echo 'До разделителя: ', mb_strrichr($path, '/', true, 'UTF-8'), "
";
echo 'От разделителя: ', mb_strrichr($path, '/', false, 'UTF-8'), "
";
Ожидаемый результат
До разделителя: Дом/Склад
От разделителя: /Офис
Третий аргумент задаёт сторону, а не чувствительность к регистру. / входит только в правую часть. Это удобно для собственного простого формата подписи, если / запрещён внутри названий. Функция не разбирает путь файловой системы и не проверяет доступ к каталогу.
<?php
$comment = 'Статус: принят; СТАТУС: выдан';
$part = mb_strrichr($comment, 'статус:', false, 'UTF-8');
echo $part === false ? "Отметка отсутствует
" : 'Найдено: ' . $part . "
";
$missing = mb_strrichr($comment, 'Ошибка:', false, 'UTF-8');
if ($missing === false) {
echo "В этой заметке нет метки ошибки
";
}
Ожидаемый результат
Найдено: СТАТУС: выдан
В этой заметке нет метки ошибки
Результат сохраняет исходные буквы, даже когда поиск не учитывает регистр. false означает, что подстроки не было. Это поиск в известном тексте, а не проверка реального состояния заказа: для работы с API используют структурированные поля ответа.
<?php
$before = mb_strrichr('Кисть широкая', 'Кисть', true, 'UTF-8');
if ($before === false) {
echo "Слово не найдено
";
} else {
echo 'Слово найдено. До него: [', $before, "]
";
}
Ожидаемый результат
Слово найдено. До него: []
Метка стоит в начале, поэтому перед ней ничего нет. Это успешный пустой результат, а не false. Проверка if (!$before) смешала бы два разных исхода. В mb_strrchr/mb_strrichr текущего PHP искомая строка используется целиком; поведение нельзя переносить с байтовой strrchr.
Ошибки и границы. Пустой needle разрешён с 8.0; для такой границы возможен пустой успешный результат. Неизвестная кодировка — ValueError, nullable encoding с 8.0. Не разрезает графемы по их визуальному смыслу и не выполняет HTML-экранирование.
Рядом: mb_strstr, mb_stristr, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_substr_countПеред сборкой уведомления нужно узнать, сколько раз шаблон использует метку номера заказа. mb_substr_count считает неперекрывающиеся вхождения буквальной подстроки. Это не число слов и не поиск по регулярному выражению.
PHP 4.3+ · mbstring
mb_substr_count(string $haystack, string $needle, ?string $encoding = null): int- Шаблон содержит {{номер}} в двух местах.
- mb_substr_count возвращает 2 для точной метки.
- Затем str_replace подставляет 42, и получается готовое уведомление.
| Аргумент / результат | Что передать и получить |
|---|---|
| haystack | Текст для подсчёта. |
| needle | Непустая подстрока, регистр учитывается. |
| encoding = null | Имя кодировки исходных байтов. null или пропуск использует текущее mb_internal_encoding(); явное UTF-8 делает локальный пример независимым от чужих настроек. Это не преобразование входа. |
| return | Целое число неперекрывающихся совпадений, 0 при отсутствии. |
<?php
$template = 'Заказ {{номер}} готов. Назовите {{номер}} на выдаче.';
echo 'Метка встречается: ', mb_substr_count($template, '{{номер}}', 'UTF-8'), " раза\n";
echo str_replace('{{номер}}', '42', $template), "\n";
Ожидаемый результат
Метка встречается: 2 раза
Заказ 42 готов. Назовите 42 на выдаче.
Подсчёт сам ничего не заменил. str_replace подходит для точной замены целой UTF-8-подстроки без mb-префикса. Если значения могут содержать другие метки, сравните поведение последовательных замен и strtr с картой.
<?php
echo 'Пара аа внутри ааа: ', mb_substr_count('ааа', 'аа', 'UTF-8'), "\n";
echo 'Подстрока заказ: ', mb_substr_count('заказ заказчик', 'заказ', 'UTF-8'), "\n";
echo 'Метка с другим регистром: ', mb_substr_count('Заказ', 'заказ', 'UTF-8'), "\n";
Ожидаемый результат
Пара аа внутри ааа: 1
Подстрока заказ: 2
Метка с другим регистром: 0
После первого аа поиск продолжается за занятым диапазоном, поэтому перекрывающаяся пара не считается. В слове заказчик подстрока заказ тоже присутствует. Для числа самостоятельных слов нужны границы слов, а для нечувствительности к регистру — явно выбранная нормализация. Пустая искомая строка вызывает ValueError.
Ошибки и границы. Пустой needle вызывает ValueError в PHP 8; неизвестная кодировка также ValueError. null encoding разрешён с 8.0. Подсчёт подстрок не является подсчётом слов: заказ встречается внутри заказчик.
Рядом: mb_strpos, mb_stripos, mb_substr. Байты, кодовые точки и графемы; общие правила вызова.
mb_regex_encodingВ старом приложении используются mb_ereg и другие функции Oniguruma. Чтобы русский шаблон находил русское название, движок должен одинаково читать шаблон и текст. mb_regex_encoding задаёт именно эту настройку; кодировка обычных mb-строк хранится отдельно.
PHP 4.2+ · mbstring
mb_regex_encoding(?string $encoding = null): string|bool- Шаблон Кисть и строка Кисть: 12 сохранены в UTF-8.
- Движок mbregex явно получает настройку UTF-8.
- Из найденного фрагмента извлекаем количество 12.
| Аргумент / результат | Что передать и получить |
|---|---|
| encoding | Поддерживаемое mbregex имя; null/пропуск читает текущее значение. Не каждая кодировка mb_convert_encoding доступна regex. |
| return | Строка при чтении; true при успешной записи, сигнатура включает false. |
<?php
$previous = mb_regex_encoding();
try {
mb_regex_encoding('UTF-8');
echo 'Движок читает: ', mb_regex_encoding(), "\n";
if (mb_ereg('Кисть: ([0-9]+)', 'Кисть: 12', $parts)) {
echo 'Остаток: ', $parts[1], " шт.\n";
}
} finally {
mb_regex_encoding($previous);
}
Ожидаемый результат
Движок читает: UTF-8
Остаток: 12 шт.
[0-9]+ означает одну или несколько цифр, скобки сохраняют их в группе 1. Шаблон mbregex не окружают разделителями /.../u из PCRE. try/finally возвращает прежнюю настройку, чтобы не повлиять на следующий код.
<?php
$internal = mb_internal_encoding();
$regex = mb_regex_encoding();
try {
mb_internal_encoding('ASCII');
mb_regex_encoding('UTF-8');
echo 'Строковые функции по умолчанию: ', mb_internal_encoding(), "\n";
echo 'Регулярные выражения: ', mb_regex_encoding(), "\n";
mb_ereg('(Кисть)', 'Кисть: 12', $parts);
echo 'Найдено: ', $parts[1], "\n";
} finally {
mb_internal_encoding($internal);
mb_regex_encoding($regex);
}
Ожидаемый результат
Строковые функции по умолчанию: ASCII
Регулярные выражения: UTF-8
Найдено: Кисть
ASCII выбрана только для демонстрации независимости настроек; она не подходит как общий default русскоязычного сайта. mb_regex_encoding не перекодирует ни строку, ни шаблон. Если вход не UTF-8, сначала согласуют или преобразуют его кодировку.
Ошибки и границы. Неизвестная/неподдерживаемая regex-кодировка вызывает ValueError в PHP 8.5; null разрешён с 8.0. Глобальный default не позволяет независимо чередовать два stateful поиска без согласования.
Рядом: mb_internal_encoding, mb_regex_set_options, mb_ereg. Байты, кодовые точки и графемы; общие правила вызова.
mb_regex_set_optionsОдин и тот же шаблон должен либо учитывать регистр, либо принимать «заказ» и «ЗАКАЗ». Опции задают это поведение и выбранный синтаксис mbregex. Они не совпадают с привычными флагами preg_match; особенно различается смысл m.
PHP 4.3+ · mbstring
mb_regex_set_options(?string $options = null): string- Без i шаблон заказ не находит ЗАКАЗ.
- С i находятся оба написания.
- Локальные options отдельной функции предпочтительнее изменения общего default для всего приложения.
| Аргумент / результат | Что передать и получить |
|---|---|
| options | Строка флагов; один символ режима синтаксиса ставят последним. null/пропуск только читает. |
| return | В PHP 8 запись возвращает предыдущие опции; чтение возвращает текущие. До PHP 8 запись возвращала новые. |
| Флаг | Смысл |
|---|---|
| i | Регистронезависимый поиск (ambiguity match) |
| x | Расширенная запись шаблона с пробелами/комментариями по синтаксису движка |
| m | Точка захватывает также перевод строки; не переносите сюда смысл PCRE m |
| s | ^/$ получают смысл \A/\Z |
| p | Вместе m и s |
| l | Предпочитать длиннейшее совпадение |
| n | Игнорировать пустые совпадения |
| e | Историческое выполнение замены как PHP; deprecated 7.1, удалено 8.0 — ValueError |
| Режим | Синтаксис |
|---|---|
| j | Java |
| u | GNU regex |
| g | grep |
| c | Emacs |
| r | Ruby |
| z | Perl |
| b | POSIX Basic |
| d | POSIX Extended |
<?php
mb_regex_encoding('UTF-8');
$previous = mb_regex_set_options('ir');
try {
if (mb_ereg('заказ ([0-9]+)', 'ЗАКАЗ 42', $parts)) {
echo 'Номер: ', $parts[1], "\n";
}
} finally {
mb_regex_set_options($previous);
}
Ожидаемый результат
Номер: 42
i включает сопоставление без регистра, r выбирает Ruby-синтаксис. В PHP 8 setter возвращает предыдущую строку опций; её сохраняем для finally. Старые версии возвращали новые опции, поэтому старый пример восстановления надо читать с учётом версии.
<?php
mb_regex_encoding('UTF-8');
$text = "Начало\nКонец";
foreach (['r', 'mr'] as $options) {
$found = mb_ereg_match('Начало.Конец', $text, $options);
echo $options, ': ', $found ? 'весь фрагмент найден' : 'точка не прошла перевод строки', "\n";
}
Ожидаемый результат
r: точка не прошла перевод строки
mr: весь фрагмент найден
В Oniguruma-флаге m точка захватывает перевод строки. Не переносите сюда значение PCRE m. Опции переданы непосредственно конкретному вызову: общий default не изменился. Для буквального поиска одной строки регулярное выражение вообще не требуется.
Ошибки и границы. Флаг e в PHP 8 — ValueError; старые инструкции с eval нельзя переносить. Синтаксический режим один, флагов несколько. Применимость/ошибки шаблона зависят от выбранного синтаксиса; произвольный набор букв не является безопасной пользовательской настройкой.
Рядом: mb_ereg_match, mb_ereg_replace, mb_regex_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_eregВ уведомлении поставщика есть номер заказа внутри текста: «Заказ 42 готов». mb_ereg ищет фрагмент по шаблону и возвращает захваченные части через отдельную переменную. Регистр букв по умолчанию важен; для варианта без регистра есть mb_eregi.
PHP 4.2+ · mbstring
mb_ereg(string $pattern, string $string, array &$matches = null): bool- Заказ 42 готов → шаблон Заказ ([0-9]+).
- Группа 0 содержит весь найденный фрагмент, группа 1 — только 42.
- Номер можно показать оператору или проверить по каталогу заказов.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Шаблон Oniguruma без разделителей /.../. |
| string | Текст в текущей mb_regex_encoding. |
| matches | Необязательная выходная переменная: [0] — всё совпадение, [1] и далее — группы скобок; при отсутствии совпадения пустой массив. |
| return | В PHP 8 true при найденном совпадении, false при отсутствии/ошибке. Это больше не длина совпадения. |
<?php
mb_regex_encoding('UTF-8');
$found = mb_ereg('Заказ ([0-9]+)', 'Заказ 42 готов', $parts);
if ($found) {
echo 'Полный фрагмент: ', $parts[0], "\n";
echo 'Номер: ', $parts[1], "\n";
}
Ожидаемый результат
Полный фрагмент: Заказ 42
Номер: 42
Скобки в шаблоне создают группу, [0-9] выбирает цифру, + разрешает несколько цифр подряд. $parts передаётся как выходная переменная; знак & уже указан в сигнатуре функции. Успешный ответ PHP 8 — bool, сам номер находится в $parts[1].
<?php
mb_regex_encoding('UTF-8');
$messages = ['Заказ 42 готов', 'Поставка отложена'];
foreach ($messages as $message) {
if (mb_ereg('Заказ ([0-9]+)', $message, $parts)) {
echo 'Проверить заказ №', $parts[1], "\n";
} else {
echo 'В сообщении нет номера: ', $message, "\n";
}
}
Ожидаемый результат
Проверить заказ №42
В сообщении нет номера: Поставка отложена
После неудачного поиска не читаем старые группы: в современных версиях массив очищается. Шаблон заранее известен и корректен; произвольная ошибка шаблона также может вернуть false с предупреждением, и её не следует называть обычным отсутствием номера. Извлечение цифр ещё не подтверждает существование заказа или право доступа к нему.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. До 8.0 успешный результат мог быть длиной в байтах или 1; современный код должен ожидать bool.
Рядом: mb_ereg_match, mb_eregi, mb_ereg_search_regs. Байты, кодовые точки и графемы; общие правила вызова.
mb_eregiВ уведомлении поставщика есть номер заказа внутри текста: «ЗАКАЗ 42 готов». mb_eregi ищет фрагмент по шаблону и возвращает захваченные части через отдельную переменную. Регистр подписи при этом не важен.
PHP 4.2+ · mbstring
mb_eregi(string $pattern, string $string, array &$matches = null): bool- ЗАКАЗ 42 готов → шаблон заказ ([0-9]+).
- Группа 0 содержит весь найденный фрагмент, группа 1 — только 42.
- Номер можно показать оператору или проверить по каталогу заказов.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Шаблон Oniguruma без разделителей /.../. |
| string | Текст в текущей mb_regex_encoding. |
| matches | Необязательная выходная переменная: [0] — всё совпадение, [1] и далее — группы скобок; при отсутствии совпадения пустой массив. |
| return | В PHP 8 true при найденном совпадении, false при отсутствии/ошибке. Это больше не длина совпадения. |
<?php
mb_regex_encoding('UTF-8');
$found = mb_eregi('заказ ([0-9]+)', 'ЗАКАЗ 42 готов', $parts);
if ($found) {
echo 'Полный фрагмент: ', $parts[0], "\n";
echo 'Номер: ', $parts[1], "\n";
}
Ожидаемый результат
Полный фрагмент: ЗАКАЗ 42
Номер: 42
Скобки в шаблоне создают группу, [0-9] выбирает цифру, + разрешает несколько цифр подряд. $parts передаётся как выходная переменная; знак & уже указан в сигнатуре функции. Успешный ответ PHP 8 — bool, сам номер находится в $parts[1].
<?php
mb_regex_encoding('UTF-8');
$messages = ['ЗАКАЗ 42 готов', 'Поставка отложена'];
foreach ($messages as $message) {
if (mb_eregi('заказ ([0-9]+)', $message, $parts)) {
echo 'Проверить заказ №', $parts[1], "\n";
} else {
echo 'В сообщении нет номера: ', $message, "\n";
}
}
Ожидаемый результат
Проверить заказ №42
В сообщении нет номера: Поставка отложена
После неудачного поиска не читаем старые группы: в современных версиях массив очищается. Шаблон заранее известен и корректен; произвольная ошибка шаблона также может вернуть false с предупреждением, и её не следует называть обычным отсутствием номера. Извлечение цифр ещё не подтверждает существование заказа или право доступа к нему.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. До 8.0 успешный результат мог быть длиной в байтах или 1; современный код должен ожидать bool.
Рядом: mb_ereg_match, mb_ereg, mb_ereg_search_regs. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_matchПеред поиском товара нужно принять артикул определённого вида: две латинские буквы, дефис, две цифры. mb_ereg_match начинает проверку с начала строки, но конец следует указать явно. Иначе правильный префикс может скрыть лишний текст.
PHP 4.2+ · mbstring
mb_ereg_match(string $pattern, string $string, ?string $options = null): bool- AB-42 соответствует правилу целиком.
- AB-42! содержит подходящее начало, но лишний конец.
- Якорь \z требует конец строки и отклоняет лишний знак.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Шаблон, который автоматически сопоставляется с началом; для полного поля нужен якорь конца \z. |
| string | Проверяемый текст. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | true/false; captures не возвращаются. |
<?php
mb_regex_encoding('UTF-8');
echo mb_ereg_match('[0-9]+', '42x', 'r') ? "Префикс 42 подошёл\n" : "Не подошёл\n";
echo mb_ereg_match('[0-9]+\z', '42x', 'r') ? "Поле подошло\n" : "Поле целиком не число\n";
Ожидаемый результат
Префикс 42 подошёл
Поле целиком не число
Первый шаблон остановился после цифр и не потребовал конец. Второй использует \z. Это проверка формата, а не числового диапазона и не преобразование строки в int.
<?php
mb_regex_encoding('UTF-8');
foreach (['AB-42', 'xx AB-42', 'AB-42!'] as $code) {
$valid = mb_ereg_match('[A-Z]{2}-[0-9]{2}\z', $code, 'r');
echo $code, ': ', $valid ? 'можно искать в каталоге' : 'нужен формат AB-42', "\n";
}
Ожидаемый результат
AB-42: можно искать в каталоге
xx AB-42: нужен формат AB-42
AB-42!: нужен формат AB-42
{2} требует ровно два знака; дефис здесь обычный литерал. Начало добавляет сама функция. Для ASCII-артикула preg_match тоже подходит; mbregex не обязателен. Успешный формат не означает, что товар существует.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. options nullable с 8.0.
Рядом: mb_ereg, mb_regex_set_options, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_replaceРедактору нужно привести подписи заказов к новому формату, сохранив номера. Замена по шаблону находит подпись и захватывает число, затем вставляет его в новый текст. mb_ereg_replace учитывает регистр, если явно не выбраны другие опции.
PHP 4.2+ · mbstring
mb_ereg_replace(string $pattern, string $replacement, string $string, ?string $options = null): string|false|null- Заказ 42; Заказ 43 содержит две подписи.
- ([0-9]+) сохраняет каждый номер отдельно.
- В результате появляются заявки №42 и №43, а оригинальная строка остаётся в своей переменной.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Шаблон Oniguruma. |
| replacement | Текст замены; \1, \2… могут ссылаться на захваченные группы. В PHP-строке обратную косую нужно сохранить корректным quoting. |
| string | Текст для обработки. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | Новая строка; false при regex-ошибке; null для недопустимых байтов текущей кодировки. Отсутствие совпадений оставляет строку. |
<?php
mb_regex_encoding('UTF-8');
$text = 'Заказ 42; Заказ 43';
$result = mb_ereg_replace('Заказ', 'Заявка', $text);
echo $result, "\n";
echo 'Оригинал: ', $text, "\n";
Ожидаемый результат
Заявка 42; Заявка 43
Оригинал: Заказ 42; Заказ 43
Это простейший шаг без групп. Если нужна только буквальная замена с учётом регистра, str_replace проще. mbregex имеет смысл, когда правило действительно содержит шаблон, как в следующем примере.
<?php
mb_regex_encoding('UTF-8');
$text = 'Заказ 42; Заказ 43';
$result = mb_ereg_replace('Заказ ([0-9]+)', 'Заявка №\\1', $text);
if ($result === false || $result === null) {
throw new RuntimeException('Не удалось преобразовать подписи');
}
echo $result, "\n";
Ожидаемый результат
Заявка №42; Заявка №43
В одинарной PHP-строке две обратные косые дают одну для механизма замены; \1 означает первую захваченную группу. false и null проверяют строго: это ошибки, а не готовая пустая строка. Для вычисляемой замены используют callback, не выполнение сгенерированного PHP-кода.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. Проверка корректности входа с результатом null введена в 7.1; options nullable с 8.0. Старый eval-флаг e deprecated с 7.1 и удалён в 8.0: применяется callback, не eval.
Рядом: mb_ereg_replace_callback, mb_eregi_replace, mb_regex_set_options. Байты, кодовые точки и графемы; общие правила вызова.
mb_eregi_replaceРедактору нужно привести подписи заказов к новому формату, сохранив номера. Замена по шаблону находит подпись и захватывает число, затем вставляет его в новый текст. mb_eregi_replace принимает разные регистры подписи.
PHP 4.2+ · mbstring
mb_eregi_replace(string $pattern, string $replacement, string $string, ?string $options = null): string|false|null- ЗАКАЗ 42; Заказ 43 содержит две подписи.
- ([0-9]+) сохраняет каждый номер отдельно.
- В результате появляются заявки №42 и №43, а оригинальная строка остаётся в своей переменной.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Шаблон Oniguruma. |
| replacement | Текст замены; \1, \2… могут ссылаться на захваченные группы. В PHP-строке обратную косую нужно сохранить корректным quoting. |
| string | Текст для обработки. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | Новая строка; false при regex-ошибке; null для недопустимых байтов текущей кодировки. Отсутствие совпадений оставляет строку. |
<?php
mb_regex_encoding('UTF-8');
$text = 'ЗАКАЗ 42; Заказ 43';
$result = mb_eregi_replace('заказ', 'Заявка', $text);
echo $result, "\n";
echo 'Оригинал: ', $text, "\n";
Ожидаемый результат
Заявка 42; Заявка 43
Оригинал: ЗАКАЗ 42; Заказ 43
Это простейший шаг без групп. Если нужна только буквальная замена с учётом регистра, str_replace проще. mbregex имеет смысл, когда правило действительно содержит шаблон, как в следующем примере.
<?php
mb_regex_encoding('UTF-8');
$text = 'ЗАКАЗ 42; Заказ 43';
$result = mb_eregi_replace('заказ ([0-9]+)', 'Заявка №\\1', $text);
if ($result === false || $result === null) {
throw new RuntimeException('Не удалось преобразовать подписи');
}
echo $result, "\n";
Ожидаемый результат
Заявка №42; Заявка №43
В одинарной PHP-строке две обратные косые дают одну для механизма замены; \1 означает первую захваченную группу. false и null проверяют строго: это ошибки, а не готовая пустая строка. Для вычисляемой замены используют callback, не выполнение сгенерированного PHP-кода.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. Проверка корректности входа с результатом null введена в 7.1; options nullable с 8.0. Старый eval-флаг e deprecated с 7.1 и удалён в 8.0: применяется callback, не eval.
Рядом: mb_ereg_replace_callback, mb_ereg_replace, mb_regex_set_options. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_replace_callbackТекст уведомления содержит метки {{товар}} и {{город}}, а значения уже получены из заказа. Callback получает каждое найденное совпадение и возвращает подходящую подстановку. Так обычная PHP-функция участвует в построении текста без eval и без ручного поиска каждого места.
PHP 5.4.1+ · mbstring
mb_ereg_replace_callback(string $pattern, callable $callback, string $string, ?string $options = null): string|false|null- Движок находит {{товар}}.
- Callback получает массив: [0]={{товар}}, [1]=товар.
- return отдаёт Кисть, и она занимает место метки в готовом уведомлении.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Шаблон поиска. |
| callback | Вызываемая функция получает массив captures и должна вернуть строку замены. matches[0] — всё, [1] и далее — группы. |
| string | Текст для обработки. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | Новая строка; false при regex-ошибке; null при неверной кодировке входа. Исключение callback проходит наружу. |
<?php
mb_regex_encoding('UTF-8');
function nextPlace($parts) {
return 'место ' . ((int) $parts[1] + 1);
}
$text = mb_ereg_replace_callback('место ([0-9]+)', 'nextPlace', 'место 4; место 8');
echo $text, "\n";
Ожидаемый результат
место 5; место 9
Функцию nextPlace вызывает движок дважды. В первый раз группа 1 содержит строку 4, приведение int и +1 дают число 5; return отдаёт строку «место 5». Во второй раз аналогично получается 9. echo внутри callback здесь не нужен: текст возвращается в замену.
<?php
mb_regex_encoding('UTF-8');
$values = ['товар' => 'Кисть', 'город' => 'Тула'];
$template = '{{товар}} ждёт вас: {{город}}. Цена: {{цена}}.';
$result = mb_ereg_replace_callback('\{\{([а-я]+)\}\}', function ($parts) use ($values) {
return $values[$parts[1]] ?? $parts[0];
}, $template);
if ($result === false || $result === null) {
throw new RuntimeException('Не удалось собрать уведомление');
}
echo $result, "\n";
Ожидаемый результат
Кисть ждёт вас: Тула. Цена: {{цена}}.
use передаёт готовую карту замыканию. Неизвестная метка осталась заметной — отправку такого сообщения можно отклонить на следующем шаге. Шаблон допускает только заданный набор русских букв; это намеренно маленький текстовый формат. HTML-шаблону потребуются контекстные правила экранирования. Данные лучше получить до callback, а не выполнять запрос на каждую метку.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. Невызываемый callback — TypeError. Неверная строка даёт null с 7.1, options nullable с 8.0. Не выполняйте сетевой запрос внутри callback для каждого слова: сначала получите данные и передайте готовую карту.
Рядом: mb_ereg_replace, mb_ereg, mb_regex_set_options. Байты, кодовые точки и графемы; общие правила вызова.
mb_splitВ простом списке категорий пользователь может поставить запятую или точку с запятой. mb_split разбивает текст по regex-разделителю и возвращает массив. Когда разделитель один и буквально известен, достаточно explode; CSV с кавычками требует отдельного парсера.
PHP 4.2+ · mbstring
mb_split(string $pattern, string $string, int $limit = -1): array|false- Кисти,Валики;Перчатки — одна строка.
- [,;] выбирает каждый из двух разделителей.
- Получается массив из трёх названий для дальнейшей проверки.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern | Regex-разделитель, не буквальная строка. |
| string | Текст в mb_regex_encoding. |
| limit | Положительный максимум частей; последняя содержит остаток. Отрицательный — без ограничения. В 8.5 значение 0 ведёт себя как 1; используйте -1 или явное положительное. |
| return | Массив частей; false при ошибке. Пустые части на границах могут сохраняться. |
<?php
mb_regex_encoding('UTF-8');
$categories = mb_split('[,;]', 'Кисти,Валики;Перчатки');
foreach ($categories as $number => $category) {
echo $number + 1, '. ', $category, "\n";
}
Ожидаемый результат
1. Кисти
2. Валики
3. Перчатки
Квадратные скобки внутри шаблона означают один символ из набора. foreach проходит полученный массив. Для внешнего поля результат сначала проверяют на false и ограничивают размер; здесь шаблон и вход фиксированы.
<?php
mb_regex_encoding('UTF-8');
$parts = mb_split(':', 'товар:Кисть:широкая', 2);
echo 'Тип записи: ', $parts[0], "\n";
echo 'Описание: ', $parts[1], "\n";
Ожидаемый результат
Тип записи: товар
Описание: Кисть:широкая
Лимит 2 разрешает не более двух частей, поэтому остаток содержит второе двоеточие. До обращения к элементу 1 у произвольного ввода проверяют число частей. Для строго буквального двоеточия explode с тем же лимитом проще.
<?php
mb_regex_encoding('UTF-8');
$parts = mb_split('[,;]', ';Кисти,,Валики;');
foreach ($parts as $index => $part) {
echo $index, ': [', $part, "]\n";
}
Ожидаемый результат
0: []
1: [Кисти]
2: []
3: [Валики]
4: []
Разделитель не означает автоматическую валидацию списка. Пустые элементы можно явно отклонить или удалить по правилам формы. Не применяйте этот способ к CSV, где запятая может находиться внутри кавычек.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. Большой вход без limit создаёт большой массив. Не путайте mb_str_split (фиксированные группы символов) и mb_split (regex-разделитель).
Рядом: mb_ereg, mb_str_split, mb_regex_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_search_initНужно последовательно извлечь номера из длинного уведомления, а не искать всё заново с начала. init сохраняет текст и шаблон для семейства mb_ereg_search_*. Это только подготовка: результат появится при следующем поисковом вызове.
PHP 4.2+ · mbstring
mb_ereg_search_init(string $string, ?string $pattern = null, ?string $options = null): bool- Текст №42; №43 сохраняется вместе с шаблоном цифр.
- Курсор устанавливается на байт 0.
- Первый search_regs найдёт 42, второй — 43.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Новый текст; курсор начинается с нуля. |
| pattern = null | Новый шаблон или null для последнего установленного через init/поиск. Не означает любой текст. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | true при успешной подготовке; false при ошибке. Само совпадение ещё не извлекается. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
echo 'Курсор после подготовки: ', mb_ereg_search_getpos(), "\n";
$parts = mb_ereg_search_regs();
echo 'Первый номер: ', $parts[0], "\n";
$parts = mb_ereg_search_regs();
echo 'Второй номер: ', $parts[0], "\n";
Ожидаемый результат
Курсор после подготовки: 0
Первый номер: 42
Второй номер: 43
Два вызова regs продолжают один поиск, а не повторяют первый. [0-9]+ не может совпасть с пустой строкой, поэтому курсор продвигается. В произвольном вводе каждый результат проверяют на false до чтения [0].
<?php
mb_regex_encoding('UTF-8');
$messages = ['Сегодня №42; №43', 'Завтра №50'];
foreach ($messages as $message) {
mb_ereg_search_init($message, '[0-9]+');
echo 'Уведомление: ', $message, "\n";
while (($parts = mb_ereg_search_regs()) !== false) {
echo ' Проверить заказ ', $parts[0], "\n";
}
}
Ожидаемый результат
Уведомление: Сегодня №42; №43
Проверить заказ 42
Проверить заказ 43
Уведомление: Завтра №50
Проверить заказ 50
Новый init заменяет предыдущий текст и состояние. Поэтому его нельзя неожиданно вызывать внутри callback другого активного поиска. Этот учебный формат содержит только номера заказов; для произвольных уведомлений уточняют шаблон, чтобы не спутать заказ с датой или суммой.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. pattern/options nullable с 8.0. Устанавливайте pattern явно для независимого разбора, вместо надежды на оставшийся от предыдущей операции.
Рядом: mb_ereg_search_regs, mb_ereg_search_getpos, mb_regex_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_searchТекст и шаблон уже подготовлены через init. mb_ereg_search передвигается к следующему совпадению и сообщает, найдено ли оно. Сам найденный номер читают отдельной функцией getregs; когда больше номеров нет, цикл заканчивается.
PHP 4.2+ · mbstring
mb_ereg_search(?string $pattern = null, ?string $options = null): bool- Первый search → true, сохранён номер 42.
- Второй search → true, сохранён номер 43.
- Третий search → false: в этом тексте больше номеров нет.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern = null | Новый шаблон или null для последнего установленного через init/поиск. Не означает любой текст. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | true при следующем совпадении; false при отсутствии или ошибке. Последние captures доступны через getregs. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
if (mb_ereg_search()) {
$parts = mb_ereg_search_getregs();
echo 'Найден заказ: ', $parts[0], "\n";
}
Ожидаемый результат
Найден заказ: 42
search возвращает bool, а не строку 42. getregs читает уже найденное и не двигает курсор. Это две отдельные операции; search_regs объединяет поиск и получение массива в одном вызове.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
$count = 0;
while (mb_ereg_search()) {
$parts = mb_ereg_search_getregs();
echo 'Добавить к проверке: заказ ', $parts[0], "\n";
$count++;
}
echo 'Номеров найдено: ', $count, "\n";
Ожидаемый результат
Добавить к проверке: заказ 42
Добавить к проверке: заказ 43
Номеров найдено: 2
Пример выводит план проверок, ничего не отправляет в реальную очередь. Пока условие true, тело обрабатывает текущий номер. false может также сопровождать ошибку движка; предупреждения нельзя скрывать и считать успешным окончанием импорта. Размер входа и число результатов должны иметь предел.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. Неинициализированное состояние/отсутствующий шаблон может вызвать Error в PHP 8. Неверный поток вызовов — ошибка программы, не пустой документ. pattern/options nullable с 8.0.
Рядом: mb_ereg_search_init, mb_ereg_search_getregs, mb_ereg_search_pos. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_search_posКроме самого номера бывает нужно знать его место в исходном тексте: для разбора протокола, отметки проблемного участка или последующей замены. search_pos возвращает байтовое начало и длину следующего совпадения. Эти числа можно передать substr для той же неизменённой строки.
PHP 4.2+ · mbstring
mb_ereg_search_pos(?string $pattern = null, ?string $options = null): array|false- В №42 знак № занимает три байта UTF-8.
- Цифры 42 начинаются с байта 3 и занимают 2 байта.
- substr($text, 3, 2) возвращает именно 42.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern = null | Новый шаблон или null для последнего установленного через init/поиск. Не означает любой текст. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | [offset, length] в байтах от начала исходного текста; false при отсутствии/ошибке. Вызов передвигает курсор. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
$text = '№42; №43';
mb_ereg_search_init($text, '[0-9]+');
$range = mb_ereg_search_pos();
echo 'Начало: ', $range[0], '; длина: ', $range[1], " байта\n";
echo 'Фрагмент: ', substr($text, $range[0], $range[1]), "\n";
Ожидаемый результат
Начало: 3; длина: 2 байта
Фрагмент: 42
Массив содержит координаты, а не группы. mb_substr здесь был бы ошибкой: у него индексы символов, а у полученных координат единицы — байты. Текст нельзя перекодировать или изменить до использования диапазона.
<?php
mb_regex_encoding('UTF-8');
$text = '№42; №43';
mb_ereg_search_init($text, '[0-9]+');
while (($range = mb_ereg_search_pos()) !== false) {
echo 'Байт ', $range[0], ': заказ ', substr($text, $range[0], $range[1]), "\n";
}
Ожидаемый результат
Байт 3: заказ 42
Байт 10: заказ 43
Второй диапазон начинается на байте 10, хотя по видимым знакам кажется ближе. В браузере индексы JavaScript имеют ещё другую единицу — UTF-16; байтовые координаты нельзя напрямую использовать для выделения текста в DOM. Для захваченных полей удобнее search_regs.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. Требуется init; pattern/options nullable с 8.0. Не смешивайте единицы измерения при подсветке в браузере, где индекс JavaScript строки обычно в UTF-16 кодовых единицах.
Рядом: mb_ereg_search_regs, mb_ereg_search_getpos, mb_strpos. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_search_regsУведомление содержит пары «заказ — состояние». search_regs за один вызов находит следующую пару и возвращает группы: номер отдельно, состояние отдельно. Так текст можно превратить в обычные записи массива, которые дальше удобно перебирать.
PHP 4.2+ · mbstring
mb_ereg_search_regs(?string $pattern = null, ?string $options = null): array|false- Заказ 42: готов → группа 1 равна 42, группа 2 равна готов.
- Следующий вызов даёт Заказ 43: отложен.
- После исчерпания текста возвращается false, цикл завершается.
| Аргумент / результат | Что передать и получить |
|---|---|
| pattern = null | Новый шаблон или null для последнего установленного через init/поиск. Не означает любой текст. |
| options = null | Локальные флаги/один режим синтаксиса; null/пропуск использует текущие mb_regex_set_options. Флаги mbregex не равны флагам preg_*. |
| return | Массив: [0] полный фрагмент, [1] первая группа и далее; false при отсутствии/ошибке. Это новый поиск, не чтение старого результата. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('Заказ 42: готов', 'Заказ ([0-9]+): ([а-я]+)');
$parts = mb_ereg_search_regs();
echo 'Фрагмент: ', $parts[0], "\n";
echo 'Номер: ', $parts[1], "\n";
echo 'Состояние: ', $parts[2], "\n";
Ожидаемый результат
Фрагмент: Заказ 42: готов
Номер: 42
Состояние: готов
Каждая пара круглых скобок создаёт свою группу. [а-я]+ — учебное ограничение состояний, не полноценное правило для всех русских слов: например, ё вне этого диапазона. Для реального протокола лучше перечислить допустимые состояния.
<?php
mb_regex_encoding('UTF-8');
$text = 'Заказ 42: готов; Заказ 43: отложен';
mb_ereg_search_init($text, 'Заказ ([0-9]+): (готов|отложен)');
$orders = [];
while (($parts = mb_ereg_search_regs()) !== false) {
$orders[] = ['id' => (int) $parts[1], 'status' => $parts[2]];
}
foreach ($orders as $order) {
echo 'Заказ №', $order['id'], ' — ', $order['status'], "\n";
}
Ожидаемый результат
Заказ №42 — готов
Заказ №43 — отложен
Вертикальная черта выбирает готов или отложен. После разбора уже не надо искать строковые фрагменты: в массиве есть id и status. Это извлечение из учебного формата; строгий импорт дополнительно выявляет пропущенные или лишние участки, дубликаты и слишком большие номера.
Ошибки и границы. Неверный шаблон вызывает E_WARNING и false; исчерпание ресурсов regex также нельзя приравнивать к нормальному отсутствию совпадения. Выбирайте короткий проверенный шаблон, ограниченный вход и не передавайте произвольный regex пользователя. Кодировка задаётся отдельно через mb_regex_encoding; regex-часть может отсутствовать в сборке. init обязателен; pattern/options nullable с 8.0. Не вызывайте regs только ради чтения найденного ранее: он уже перейдёт к следующему.
Рядом: mb_ereg_search_init, mb_ereg_search_getregs, mb_ereg_search_pos. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_search_getposПарсер уже прочитал один номер. Чтобы временно заглянуть вперёд и затем вернуться, нужно сохранить текущую позицию. getpos возвращает байтовый курсор следующего поиска, не изменяя его и не извлекая новый номер.
PHP 4.2+ · mbstring
mb_ereg_search_getpos(): int- После номера 42 курсор находится на байте 5.
- Закладка 5 сохраняется в собственной переменной.
- Следующее извлечение даёт 43; закладка пригодится для повторного чтения.
| Аргумент / результат | Что передать и получить |
|---|---|
| Параметры | Нет. Работает с общим stateful поиском. |
| return | Байтовое смещение от начала текста. После совпадения обычно указывает сразу за ним; до первого поиска после init — 0. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
echo 'До поиска: ', mb_ereg_search_getpos(), "\n";
$parts = mb_ereg_search_regs();
echo 'Прочитан номер: ', $parts[0], "\n";
echo 'После поиска: ', mb_ereg_search_getpos(), "\n";
Ожидаемый результат
До поиска: 0
Прочитан номер: 42
После поиска: 5
Три байта № и два байта цифр дают курсор 5. Он не означает пять символов или пять найденных заказов. getpos показывает позицию продолжения; search_pos отдельно возвращает начало и длину самого совпадения.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
mb_ereg_search_regs();
$bookmark = mb_ereg_search_getpos();
$preview = mb_ereg_search_regs();
echo 'Предварительно увидели: ', $preview[0], "\n";
mb_ereg_search_setpos($bookmark);
$accepted = mb_ereg_search_regs();
echo 'Прочитали при обработке: ', $accepted[0], "\n";
Ожидаемый результат
Предварительно увидели: 43
Прочитали при обработке: 43
Такое чтение вперёд бывает нужно небольшому парсеру. Закладка относится только к той же строке и состоянию; после другого init её нельзя переносить. Для независимых вложенных парсеров лучше собственный объект с курсором.
Ошибки и границы. Вызов не принимает аргументов и не начинает поиск. Порядок вызовов должен быть явным: не используйте случайное состояние от чужого кода как закладку.
Рядом: mb_ereg_search_setpos, mb_ereg_search_pos, mb_ereg_search_init. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_search_setposПосле предварительного просмотра следующего номера нужно обработать его ещё раз. setpos возвращает курсор на сохранённую байтовую границу. Сам setter не ищет совпадение: результат появится только при следующем search-вызове.
PHP 4.2+ · mbstring
mb_ereg_search_setpos(int $offset): bool- Сохранили курсор после заказа 42.
- Предварительно прочитали 43.
- Вернули сохранённую позицию и получили 43 снова.
| Аргумент / результат | Что передать и получить |
|---|---|
| offset | Байтовая позиция; отрицательная — от конца строки (с 7.1). Выбирайте границу символа, полученную из самого поиска или проверенного формата. |
| return | true при успешной установке; сигнатура включает false. Не извлекает совпадение. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
echo 'Первый раз: ', mb_ereg_search_regs()[0], "\n";
mb_ereg_search_setpos(0);
echo 'После возврата: ', mb_ereg_search_regs()[0], "\n";
Ожидаемый результат
Первый раз: 42
После возврата: 42
Ноль — безопасная байтовая граница начала строки. В реальном входе перед чтением [0] проверяют false. Если внутри цикла безусловно возвращаться на ноль, цикл никогда не закончит обработку.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
mb_ereg_search_regs();
$bookmark = mb_ereg_search_getpos();
$next = mb_ereg_search_regs();
echo 'Номер для предпросмотра: ', $next[0], "\n";
mb_ereg_search_setpos($bookmark);
echo 'Номер для основной обработки: ', mb_ereg_search_regs()[0], "\n";
Ожидаемый результат
Номер для предпросмотра: 43
Номер для основной обработки: 43
Не вычисляем позицию по количеству букв, а берём её у движка. Произвольное число может попасть внутрь UTF-8-буквы; формально допустимый байтовый offset ещё не означает осмысленную границу текста. Выход за диапазон в PHP 8.5 вызывает ValueError.
Ошибки и границы. После инициализации offset за допустимыми границами вызывает ValueError в PHP 8.5. Число внутри UTF-8 последовательности не является корректной пользовательской границей, даже если setter принял его. Не используйте без init.
Рядом: mb_ereg_search_getpos, mb_ereg_search_regs, mb_ereg_search_init. Байты, кодовые точки и графемы; общие правила вызова.
mb_ereg_search_getregsНайденный номер нужен и для подписи, и для следующего шага обработки. getregs читает группы последнего совпадения повторно, не переходя к следующему. Этим он отличается от search_regs, который сразу выполняет новый поиск.
PHP 4.2+ · mbstring
mb_ereg_search_getregs(): array|false- search уже нашёл 42.
- Два getregs читают один и тот же номер 42.
- Только следующий search_regs продвинется к 43.
| Аргумент / результат | Что передать и получить |
|---|---|
| Параметры | Нет. |
| return | [0] последний полный фрагмент, [1] и далее группы; false, когда доступного совпадения нет. Не обещает хранить старое совпадение после неуспешного следующего поиска. |
Перед поиском вызовите mb_ereg_search_init с собственным текстом и непустым шаблоном. Состояние одно на текущий контекст; вложенный init его заменит. Примеры используют UTF-8 и шаблоны, которые не совпадают с пустой строкой. Позиции этого семейства — байты, а не индексы mb_substr.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('№42; №43', '[0-9]+');
mb_ereg_search();
echo 'Подпись: заказ ', mb_ereg_search_getregs()[0], "\n";
echo 'Действие для заказа: ', mb_ereg_search_getregs()[0], "\n";
echo 'Следующий номер: ', mb_ereg_search_regs()[0], "\n";
Ожидаемый результат
Подпись: заказ 42
Действие для заказа: 42
Следующий номер: 43
Одинаковый результат первых двух чтений — ожидаемое поведение. Эти вызовы лишь показывают данные, они не обращаются к внешней системе. Не заменяйте getregs на search_regs в середине обработки одного заказа.
<?php
mb_regex_encoding('UTF-8');
mb_ereg_search_init('Заказ 42: готов', 'Заказ ([0-9]+): (готов)');
mb_ereg_search();
$saved = mb_ereg_search_getregs();
mb_ereg_search();
echo mb_ereg_search_getregs() === false ? "Следующего совпадения нет\n" : "Есть результат\n";
echo 'Сохранённый заказ: ', $saved[1], ' — ', $saved[2], "\n";
Ожидаемый результат
Следующего совпадения нет
Сохранённый заказ: 42 — готов
Общее состояние поиска не является архивом: после неудачи доступных групп может не быть. Своя переменная сохраняет нужные данные. Для внешнего текста сначала проверяют успех начального поиска и только потом читают группы.
Ошибки и границы. Нет аргументов; зависит от явно подготовленного состояния. false проверяется до обращения [0], иначе возникнет предупреждение доступа к не-массиву.
Рядом: mb_ereg_search, mb_ereg_search_regs, mb_ereg_search_getpos. Байты, кодовые точки и графемы; общие правила вызова.
mb_http_inputНа страницу пришёл товар «Молоток». Нужно узнать, участвовал ли входной конвертер mbstring, и одновременно увидеть сами данные. mb_http_input читает состояние обработанного типа входа; она не возвращает содержимое формы и не определяет заново кодировку произвольной строки. Здесь согласован UTF-8, автоматическая конверсия выключена.
PHP 4.0.6+ · mbstring
mb_http_input(?string $type = null): array|string|false- probe_http.py посылает URL-encoded product=Молоток и stock=8.
- PHP заполняет $_GET либо $_POST; код сначала проверяет типы и UTF-8.
- mb_http_input(G/P) может вернуть false при реально пришедших данных: конвертер их не обрабатывал.
| Аргумент / результат | Что передать и получить |
|---|---|
| type | G — GET, P — POST, C — cookie, S — разобранная строка; null/пропуск — последний обработанный вход. I — массив настроенных входных кодировок, L — тот же список строкой. |
| return | Имя для обработанного типа, false если соответствующего результата нет; I возвращает массив. Это не содержимое $_POST. |
Как увидеть результат. Здесь example.php выполняет роль сервера. Сначала запустите локальную команду php -S из README архива, затем во втором терминале python probe_http.py. Python в этом уроке — готовый небольшой HTTP-клиент, который возвращает реальные заголовки и читает тело по полученному charset. Он также сохраняет сырые байты response.bin. PHP-код не нужно запускать как обычную CLI-программу: тогда HTTP-заголовков не будет. Имя Content-Type задаёт формат, charset — кодировку, echo создаёт тело ответа.
<?php
declare(strict_types=1);
header('Content-Type: text/plain; charset=UTF-8');
$product = $_GET['product'] ?? null;
$stock = $_GET['stock'] ?? null;
if (!is_string($product) || !mb_check_encoding($product, 'UTF-8') || !is_string($stock) || !ctype_digit($stock)) {
http_response_code(400);
echo "Проверьте название и остаток\n";
exit;
}
echo $product, ' — ', $stock, " шт.\n";
$encoding = mb_http_input('G');
echo $encoding === false ? "Входной конвертер mbstring не обрабатывал эти данные\n" : 'Конвертер использовал: '.$encoding."\n";
Ожидаемый результат
HTTP 200
Content-Type: text/plain
Кодировка: utf-8
Молоток — 8 шт.
Входной конвертер mbstring не обрабатывал эти данные
Полный локальный клиент и команды лежат в архиве. product из запроса становится ключом _GET[product], stock — ключом stock; оба значения формы — строки. is_string защищает от поддельного массива; mb_check_encoding проверяет договор UTF-8; ctype_digit проверяет цифры. Конфигурация запуска намеренно задаёт mbstring.encoding_translation=0. Поэтому false здесь говорит о конвертере, а не об отсутствии товара. Селекторы G/P/C/S и I/L сохранены в контракте; они не являются именами произвольных HTTP-методов.
<?php
declare(strict_types=1);
header('Content-Type: text/plain; charset=UTF-8');
$product = $_POST['product'] ?? null;
$stock = $_POST['stock'] ?? null;
if (!is_string($product) || !mb_check_encoding($product, 'UTF-8') || !is_string($stock) || !ctype_digit($stock)) {
http_response_code(400);
echo "Проверьте название и остаток\n";
exit;
}
echo $product, ' — ', $stock, " шт.\n";
$encoding = mb_http_input('P');
echo $encoding === false ? "Входной конвертер mbstring не обрабатывал эти данные\n" : 'Конвертер использовал: '.$encoding."\n";
Ожидаемый результат
HTTP 200
Content-Type: text/plain
Кодировка: utf-8
Молоток — 8 шт.
Входной конвертер mbstring не обрабатывал эти данные
Полный локальный клиент и команды лежат в архиве. product из запроса становится ключом _POST[product], stock — ключом stock; оба значения формы — строки. is_string защищает от поддельного массива; mb_check_encoding проверяет договор UTF-8; ctype_digit проверяет цифры. Конфигурация запуска намеренно задаёт mbstring.encoding_translation=0. Поэтому false здесь говорит о конвертере, а не об отсутствии товара. Селекторы G/P/C/S и I/L сохранены в контракте; они не являются именами произвольных HTTP-методов.
Ошибки и границы. С PHP 8 неверный type — ValueError; null разрешён с 8.0. Изменение mb_internal_encoding в обработчике не выполняет заново разбор GET/POST. Настройка входного фильтра должна существовать до запроса.
Рядом: mb_parse_str, mb_check_encoding, mb_get_info. Байты, кодовые точки и графемы; общие правила вызова.
mb_http_outputЧитатель старой складской программы должен получить понятную строку «Молоток — 8 шт.». Задаёт желаемую выходную кодировку mbstring. Сам вызов не меняет уже существующие строки: нужен обработчик выходного буфера. Прежде чем подключать его к старому клиенту, сравним два настоящих ответа.
PHP 4.0.6+ · mbstring
mb_http_output(?string $encoding = null): string|bool- Файл example.php сохранён в UTF-8; строка внутри PHP содержит UTF-8 байты.
- HTTP-заголовок описывает байты; имя кодировки само по себе их не преобразует.
- probe_http.py сохраняет response.bin и читает текст по charset полученного ответа.
| Аргумент / результат | Что передать и получить |
|---|---|
| encoding | Имя кодировки назначения либо pass для отсутствия конверсии; null/пропуск читает текущее. |
| return | Строка при чтении, true при успешной записи (контракт включает false). |
Как увидеть результат. Здесь example.php выполняет роль сервера. Сначала запустите локальную команду php -S из README архива, затем во втором терминале python probe_http.py. Python в этом уроке — готовый небольшой HTTP-клиент, который возвращает реальные заголовки и читает тело по полученному charset. Он также сохраняет сырые байты response.bin. PHP-код не нужно запускать как обычную CLI-программу: тогда HTTP-заголовков не будет. Имя Content-Type задаёт формат, charset — кодировку, echo создаёт тело ответа.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
mb_http_output('Windows-1251');
header('Content-Type: text/plain; charset=UTF-8');
echo "Молоток — 8 шт.\n";
Ожидаемый результат
HTTP 200
Content-Type: text/plain
Кодировка: utf-8
Молоток — 8 шт.
Это HTTP endpoint, не CLI-вывод. Сначала запустите php -d mbstring.encoding_translation=0 -S 127.0.0.1:8793 example.php; во втором терминале python probe_http.py. Полные команды в README архива. Клиент показывает настоящие заголовки и декодированное тело; response.bin содержит исходные UTF-8 байты. Настройка Windows-1251 без конвертера их не меняет; режим pass явно выключает конверсию.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
mb_http_output('Windows-1251');
header('Content-Type: text/plain; charset=Windows-1251');
ob_start('mb_output_handler');
echo "Молоток — 8 шт.\n";
ob_end_flush();
Ожидаемый результат
HTTP 200
Content-Type: text/plain
Кодировка: windows-1251
Молоток — 8 шт.
ob_start регистрирует имя функции: PHP вызовет её при сбросе буфера. echo пока пишет внутрь буфера; ob_end_flush завершает его и отправляет преобразованное тело. Обработчик берёт исходную кодировку из mb_internal_encoding, назначение — из mb_http_output. Клиент действительно читает Windows-1251 по HTTP charset: сообщение человеку то же, байты response.bin другие. Не конвертируйте строку вручную перед этим обработчиком. Для обычного UTF-8 сайта этот слой не нужен; бинарные данные и неподходящие MIME-типы нельзя преобразовывать таким способом.
Ошибки и границы. Неизвестная кодировка вызывает ValueError в PHP 8.5. С 8.4 нулевой байт в имени также ValueError; encoding nullable с 8.0. deprecated INI mbstring.http_output не означает deprecated самой функции.
Рядом: mb_output_handler, mb_internal_encoding, mb_preferred_mime_name. Байты, кодовые точки и графемы; общие правила вызова.
mb_output_handlerЧитатель старой складской программы должен получить понятную строку «Молоток — 8 шт.». Преобразует вывод только как зарегистрированный обработчик буфера. Сначала увидим режим pass: PHP собирает текст и передаёт его без изменения кодировки. Затем включим конверсию для старого клиента.
PHP 4.0.6+ · mbstring
mb_output_handler(string $string, int $status): string- Файл example.php сохранён в UTF-8; строка внутри PHP содержит UTF-8 байты.
- HTTP-заголовок описывает байты; имя кодировки само по себе их не преобразует.
- probe_http.py сохраняет response.bin и читает текст по charset полученного ответа.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Часть содержимого буфера, которую передаёт система output buffering. |
| status | Битовые флаги жизненного цикла PHP_OUTPUT_HANDLER_*; их передаёт PHP. Приложение обычно регистрирует имя callback, не вызывает его вручную. |
| return | Строка результата, преобразованная при подходящем MIME/настройках либо переданная как есть. |
Content-Type должен быть выставлен до вывода, а MIME-тип должен соответствовать данным. text/* обычно преобразуется; image/png или application/octet-stream не должны попадать под текстовое правило. Обработка зависит от mbstring.http_output_conv_mimetypes и SAPI. Если вручную уже перевели текст в Windows-1251, повторный handler из UTF-8 испортит его. Для обычного UTF-8 сайта проще обходиться без конвертера.
Как увидеть результат. Здесь example.php выполняет роль сервера. Сначала запустите локальную команду php -S из README архива, затем во втором терминале python probe_http.py. Python в этом уроке — готовый небольшой HTTP-клиент, который возвращает реальные заголовки и читает тело по полученному charset. Он также сохраняет сырые байты response.bin. PHP-код не нужно запускать как обычную CLI-программу: тогда HTTP-заголовков не будет. Имя Content-Type задаёт формат, charset — кодировку, echo создаёт тело ответа.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
mb_http_output('pass');
header('Content-Type: text/plain; charset=UTF-8');
ob_start('mb_output_handler');
echo "Молоток — 8 шт.\n";
ob_end_flush();
Ожидаемый результат
HTTP 200
Content-Type: text/plain
Кодировка: utf-8
Молоток — 8 шт.
Это HTTP endpoint, не CLI-вывод. Сначала запустите php -d mbstring.encoding_translation=0 -S 127.0.0.1:8793 example.php; во втором терминале python probe_http.py. Полные команды в README архива. Клиент показывает настоящие заголовки и декодированное тело; response.bin содержит исходные UTF-8 байты. Настройка Windows-1251 без конвертера их не меняет; режим pass явно выключает конверсию.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
mb_http_output('Windows-1251');
header('Content-Type: text/plain; charset=Windows-1251');
ob_start('mb_output_handler');
echo "Молоток — 8 шт.\n";
ob_end_flush();
Ожидаемый результат
HTTP 200
Content-Type: text/plain
Кодировка: windows-1251
Молоток — 8 шт.
ob_start регистрирует имя функции: PHP вызовет её при сбросе буфера. echo пока пишет внутрь буфера; ob_end_flush завершает его и отправляет преобразованное тело. Обработчик берёт исходную кодировку из mb_internal_encoding, назначение — из mb_http_output. Клиент действительно читает Windows-1251 по HTTP charset: сообщение человеку то же, байты response.bin другие. Не конвертируйте строку вручную перед этим обработчиком. Для обычного UTF-8 сайта этот слой не нужен; бинарные данные и неподходящие MIME-типы нельзя преобразовывать таким способом.
Ошибки и границы. Callback имеет состояние между фрагментами буфера; для разовой строки используйте mb_convert_encoding, не ручную имитацию status. Header already sent, неверное назначение/конфликт буферов — ошибки конфигурации, а не нормальный текстовый результат. Отправка и Content-Length должны учитывать итоговые байты.
Рядом: mb_http_output, mb_internal_encoding, mb_substitute_character. Байты, кодовые точки и графемы; общие правила вызова.
mb_parse_strПартнёр передал поля как строку product=...&stock=... . Требуется получить название, остаток и список меток, а затем проверить данные. mb_parse_str разбирает URL-encoded запись по правилам PHP и настроенного входного профиля; это не разбор JSON и не подтверждение корректности товара.
PHP 4.0.6+ · mbstring
mb_parse_str(string $string, array &$result): bool- %XX раскрывает байты, + обозначает пробел.
- Имя stock даёт строку; tag[] создаёт список.
- Успех разбора ещё не означает, что stock имеет нужный тип и диапазон.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Строка вида name=value&tag[]=a; это не JSON и не multipart. Разделители зависят от arg_separator.input. |
| result | Обязательная выходная переменная-массив, передаётся по ссылке. Данные записываются сюда, не в произвольные глобальные переменные. |
| return | true при успешной обработке, false при неудаче; true не означает валидность бизнес-полей. |
Современная реализация берёт кандидатов из входной конфигурации http_input, а назначение из текущего internal encoding; одно mb_detect_order не является универсальной настройкой этого парсера. Для нового UTF-8 URL-encoded входа обычно понятнее parse_str с проверкой mb_check_encoding результата. Прямой выбор исходной таблицы в аргументах mb_parse_str отсутствует. Применяются ограничения парсинга PHP, включая max_input_vars/max_input_nesting_level; результат может оказаться неполным после предупреждения. Не считать return true доказательством полноты внешнего документа.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
$input = 'product=%D0%9A%D0%B8%D1%81%D1%82%D1%8C&stock=0&tag[]=tools&tag[]=sale';
if (!mb_parse_str($input, $fields)) { throw new RuntimeException('Поля не разобраны'); }
echo $fields['product'], ' — ', $fields['stock'], " шт.\n";
echo 'Метки: ', implode(', ', $fields['tag']), "\n";
Ожидаемый результат
Кисть — 0 шт.
Метки: tools, sale
Исходная строка полностью задана в коде и содержит UTF-8. Второй аргумент — выходная переменная; писать & при вызове не нужно. Квадратные скобки tag[] создают массив, implode соединяет его строки для человека. Значение "0" не следует отвергать через empty: нулевой остаток реален. Приёмник должен иметь согласованный входной профиль; разбор не угадывает происхождение любого файла.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
foreach (['product=Кисть&stock=0', 'product=Кисть&stock[]=8'] as $input) {
if (!mb_parse_str($input, $fields)) { throw new RuntimeException('Поля не разобраны'); }
$name = $fields['product'] ?? null;
$stock = $fields['stock'] ?? null;
if (!is_string($name) || !mb_check_encoding($name, 'UTF-8')
|| !is_string($stock) || !ctype_digit($stock) || strlen($stock) > 4) {
echo "Импорт отклонён: название и остаток должны быть строковыми полями\n";
continue;
}
echo 'Принято: ', $name, ' — ', (int)$stock, " шт.\n";
}
Ожидаемый результат
Принято: Кисть — 0 шт.
Импорт отклонён: название и остаток должны быть строковыми полями
foreach проверяет два самостоятельных входа. ?? даёт null при отсутствующем ключе, условия не допускают массив stock[]. Только после проверки цифр и длины (int) создаёт число. continue пропускает сохранение ошибочного входа. Точки/пробелы в именах и дублирующиеся ключи PHP нормализует: для подписываемого протокола согласуйте эти правила или выберите формат без неоднозначности.
Ошибки и границы. Второй аргумент обязателен с PHP 8; пропуск deprecated с 7.2. Старый заголовок страницы про global и недоступность raw POST исторический: php://input существует, но формат тела и доступность зависят от SAPI/content type. Функция не проверяет CSRF, права, HTML или SQL.
Рядом: mb_http_input, mb_internal_encoding, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_encode_mimeheaderВ почтовом списке человек должен увидеть «Кисть», хотя транспортный заголовок содержит специальную ASCII-запись. mb_encode_mimeheader кодирует значение заголовка по MIME. Она не создаёт целое письмо и не отправляет его. Сначала получим одну строку Subject, затем сохраним собственный order.eml.
PHP 4.0.6+ · mbstring
mb_encode_mimeheader(string $string, ?string $charset = null, ?string $transfer_encoding = null, string $newline = "\r\n", int $indent = 0): string- UTF-8 строка Кисть → mb_encode_mimeheader.
- Маркер =?UTF-8?B?...?= сообщает charset и Base64-представление.
- Почтовый клиент декодирует поле обратно в читаемое название.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Текст в текущей mb_internal_encoding. Это отдельное условие от выходного charset. |
| charset | Кодировка encoded-word результата; при пропуске/ null зависит от языкового профиля. Для ясного контракта задайте UTF-8. |
| transfer_encoding | B — Base64, Q — вариант quoted-printable для encoded-word. Укажите явно; default определяется вызовом/профилем. |
| newline | Маркер переноса длинного заголовка, обычно CRLF. |
| indent | Число знаков до текста на первой строке: для Subject: — 9. Это не количество отступов каждого переноса. |
| return | ASCII-строка с encoded-word; без названия заголовка Subject:. Длинный текст складывается в несколько частей. |
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
$subject = mb_encode_mimeheader('Кисть', 'UTF-8', 'B');
echo 'Subject: ', $subject, "\n";
Ожидаемый результат
Subject: =?UTF-8?B?0JrQuNGB0YLRjA==?=
Первый аргумент — обычный текст во внутренней кодировке, второй — charset результата, B — Base64; Q обозначает другой MIME-способ. Строка Subject содержит имя поля отдельно от закодированного значения. Это не base64_encode целого письма и не HTML-экранирование.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
$subject = mb_encode_mimeheader('Заказ 42: Кисть', 'UTF-8', 'B', "\r\n", 9);
$headers = ['From: shop@phpmanual.test', 'To: student@phpmanual.test',
'Subject: '.$subject, 'MIME-Version: 1.0',
'Content-Type: text/plain; charset=UTF-8', 'Content-Transfer-Encoding: 8bit'];
$mail = implode("\r\n", $headers)."\r\n\r\nКисть — 2 шт.\r\n";
if (file_put_contents(__DIR__ . '/order.eml', $mail) !== strlen($mail)) {
throw new RuntimeException('Письмо не записано полностью');
}
if (file_get_contents(__DIR__ . '/order.eml') !== file_get_contents(__DIR__ . '/EXPECTED-ORDER.eml')) {
throw new RuntimeException('Содержимое письма отличается от заданного образца');
}
echo 'Сохранён order.eml; тема: ', mb_decode_mimeheader($subject), "\n";
echo "Тело: Кисть — 2 шт.\n";
Ожидаемый результат
Сохранён order.eml; тема: Заказ 42: Кисть
Тело: Кисть — 2 шт.
order.eml появляется рядом с example.php; код сравнивает все его байты с приложенным EXPECTED-ORDER.eml, где видно точное содержимое. Заголовки разделяются CRLF, пустая строка отделяет тело. indent=9 учитывает длину префикса Subject: ; функция сама переносит длинное значение. В этом коротком письме тема помещается в одну строку. From/To заданы нами, пользовательский CR/LF в заголовки не вставляется. mb_send_mail кодирует свою тему самостоятельно: туда передают исходную тему, а не результат этой функции.
Ошибки и границы. Неизвестный/неподходящий MIME charset — ValueError. В PHP 8 параметры charset/transfer_encoding допускают null; с 8.3 NUL в Q-кодировании сохраняется как =00, а не теряется. Функция не является валидатором адреса или защитой от header injection: исходные CR/LF и другие недопустимые управляющие знаки в пользовательской теме отклоняют до сборки письма. Адрес целиком не превращают в encoded-word.
Рядом: mb_decode_mimeheader, mb_language, mb_send_mail. Байты, кодовые точки и графемы; общие правила вызова.
mb_decode_mimeheaderПри импорте письма тема выглядит как =?UTF-8?B?...?=. Человеку нужно название, а не транспортная упаковка. mb_decode_mimeheader раскрывает encoded-word и возвращает текст в mb_internal_encoding. Она не разбирает вложения и не декодирует автоматически тело MIME-письма.
PHP 4.0.6+ · mbstring
mb_decode_mimeheader(string $string): string- Файл order.eml содержит отдельное поле Subject.
- Декодер превращает его значение в UTF-8 текст.
- Импорт показывает тему и отдельно прочитанное текстовое тело.
| Аргумент / результат | Что передать и получить |
|---|---|
| string | Значение поля MIME-заголовка, которое может содержать encoded-word. |
| return | Раскодированный текст в текущей mb_internal_encoding. Это не массив всех заголовков и не тело письма. |
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
echo mb_decode_mimeheader('=?UTF-8?B?0JrQuNGB0YLRjA==?='), "\n";
Ожидаемый результат
Кисть
Закодированная строка целиком дана в примере. Внутренняя кодировка результата явно UTF-8, поэтому кириллица не теряется при конверсии в неподходящий однобайтовый профиль.
<?php
declare(strict_types=1);
mb_internal_encoding('UTF-8');
$raw = file_get_contents(__DIR__ . '/order.eml');
if ($raw === false) { throw new RuntimeException('Письмо не прочитано'); }
[$headers, $body] = explode("\r\n\r\n", $raw, 2);
foreach (explode("\r\n", $headers) as $line) {
if (str_starts_with($line, 'Subject: ')) {
echo 'Тема: ', mb_decode_mimeheader(substr($line, 9)), "\n";
}
}
echo 'Тело: ', str_replace("\r\n", "\n", $body);
Ожидаемый результат
Тема: Заказ 42: Кисть
Тело: Кисть — 2 шт.
Архив содержит order.eml, не предполагаемый внешний ящик. explode отделяет заголовки от тела по пустой строке; foreach ищет известный короткий Subject, substr убирает префикс. Это разбор конкретного приложенного письма с одной строкой темы и телом 8bit UTF-8. Общая почта требует MIME-парсера: folded fields, multipart, другие transfer encodings и вложения этим циклом не разобраны. Для HTML-показа декодированный текст дополнительно экранируют.
Ошибки и границы. Функция не обещает строгую проверку корректности всего RFC-письма. Не используйте результат как готовый безопасный HTML, имя файла или команду; валидируйте контекст назначения. Нужна функция/библиотека разбора MIME для вложений и структуры письма.
Рядом: mb_encode_mimeheader, mb_internal_encoding, mb_check_encoding. Байты, кодовые точки и графемы; общие правила вызова.
mb_send_mailНужно подготовить уведомление «Заказ 42: Кисть» и убедиться, какие тему и тело получил почтовый транспорт. В этом опыте транспорт — свой Python-приёмник на 127.0.0.1; он только сохраняет файл и не пересылает письмо. mb_send_mail выполняет MIME-кодирование по mb_language, затем передаёт результат почтовой подсистеме PHP.
PHP 4.0.6+ · mbstring
mb_send_mail(string $to, string $subject, string $message, array|string $additional_headers = [], ?string $additional_params = null): bool- Обычные UTF-8 тема и тело → профиль uni.
- Windows PHP соединяется только с 127.0.0.1:8794.
- smtp_sink.py сохраняет captured.eml; probe_mail.py декодирует настоящий файл.
- Принятие локальным SMTP не доказывает доставку в чей-либо ящик.
| Аргумент / результат | Что передать и получить |
|---|---|
| to | Один адрес или список через запятую; автоматически MIME-кодироваться не будет. Политика получателей/валидация — ответственность приложения. |
| subject | Исходная тема в согласованной internal encoding; обёртка выполняет своё кодирование, поэтому не применяйте mb_encode_mimeheader повторно заранее. |
| message | Текст тела; кодирование зависит от языкового профиля. Это не автоматическая поддержка любых вложений/HTML-шаблонов. |
| additional_headers | Массив name → value (с 7.2) либо строка заголовков, разделённых CRLF. Нужен From здесь или в серверной конфигурации. |
| additional_params | Дополнительные параметры MTA, например статически доверенный envelope sender для sendmail. Это не SMTP-пароль. Не принимать их из HTTP. |
| return | true означает принятие к отправке транспортом, не доставку получателю; false — неудачу передачи. Возможны предупреждения/ошибки конфигурации. |
additional_params проходит escapeshellcmd, но это не запрещает добавление новых параметров MTA. Используйте только доверенную фиксированную серверную настройку либо null; произвольное пользовательское значение запрещено контрактом вашего приложения. При sendmail envelope -f может потребовать настройки доверенного системного пользователя, иначе появится X-Warning. В Windows From влияет также на Return-Path. Отсутствующий From вызывает предупреждение конфигурации. Исторический обход qmail с LF вместо CRLF применялся только под конкретный MTA и не является общим стандартным рецептом.
Для очереди уведомлений обычно удобнее почтовая библиотека с явной SMTP-конфигурацией и обработкой ошибок. Многократный вызов mail-обёртки не создаёт автоматически безопасную массовую рассылку. При неопределённом результате нельзя бесконечно повторять отправку: иначе пользователю придут дубликаты. Локальный приёмник проверяет только подготовку и принятие сообщения в указанной лаборатории; внешняя доставка и DNS этим не проверяются.
Прежде чем запускать. Вызов ниже передаёт четыре значения: получатель, обычная тема, обычное тело и массив заголовков. Элемент From содержит наш фиксированный адрес; своего Subject в массиве нет. ini_set меняет настройку текущего PHP-процесса. getenv читает необязательный порт из окружения, ?: выбирает учебный порт 8794, если переменная пуста. ctype_digit и проверка диапазона подтверждают, что задан допустимый номер учебного порта. Проверка PHP_OS_FAMILY останавливает опыт вне Windows, чтобы код не попал в системный Unix MTA. Никаких адресов SMTP из формы не принимается.
<?php
declare(strict_types=1);
if (PHP_OS_FAMILY !== 'Windows') {
throw new RuntimeException('Этот SMTP-опыт требует Windows; системный MTA не вызывается');
}
$port = getenv('PHP_MANUAL_SMTP_PORT') ?: '8794';
if (!ctype_digit($port) || (int)$port < 1024 || (int)$port > 65535) {
throw new RuntimeException('Нужен локальный учебный порт');
}
ini_set('SMTP', '127.0.0.1');
ini_set('smtp_port', $port);
ini_set('sendmail_from', 'shop@phpmanual.test');
mb_internal_encoding('UTF-8');
mb_language('uni');
$accepted = mb_send_mail('student@phpmanual.test', 'Заказ 42: Кисть',
"Кисть — 2 шт.\nК выдаче: 160 руб.\n", ['From'=>'shop@phpmanual.test']);
if (!$accepted) { throw new RuntimeException('Локальный SMTP не принял письмо'); }
echo "Локальный приёмник принял сообщение\n";
Ожидаемый результат
Локальный приёмник принял сообщение
Кому: student@phpmanual.test
Тема: Заказ 42: Кисть
Формат: text/plain
Кодировка: utf-8
Тело:
Кисть — 2 шт.
К выдаче: 160 руб.
Нужны Windows PHP с mbstring и Python 3. В первом терминале python smtp_sink.py; во втором php example.php; затем python probe_mail.py. Результат ниже — вывод двух последних команд. Все файлы и команды входят в архив. ini_set изменяет только этот процесс; uni задаёт профиль UTF-8/MIME, но не адрес SMTP. Тема передаётся обычным текстом ровно один раз, дополнительный Subject не дублируется. captured.eml содержит реальные транспортные заголовки и тело, smtp-transcript.txt — ответы SMTP. На Unix этот файл останавливается до вызова почтовой подсистемы; там нужен отдельный контролируемый sendmail_path.
<?php
declare(strict_types=1);
if (PHP_OS_FAMILY !== 'Windows') {
throw new RuntimeException('Этот SMTP-опыт требует Windows; системный MTA не вызывается');
}
$port = getenv('PHP_MANUAL_SMTP_PORT') ?: '8794';
if (!ctype_digit($port) || (int)$port < 1024 || (int)$port > 65535) {
throw new RuntimeException('Нужен локальный учебный порт');
}
ini_set('SMTP', '127.0.0.1');
ini_set('smtp_port', $port);
ini_set('sendmail_from', 'shop@phpmanual.test');
mb_internal_encoding('UTF-8');
mb_language('uni');
$warning = null;
set_error_handler(function (int $level, string $message) use (&$warning): bool {
if ($level !== E_WARNING) { return false; }
$warning = $message;
return true;
});
try {
$accepted = mb_send_mail('student@phpmanual.test', 'Заказ 42: Кисть',
'Кисть — 2 шт.', ['From'=>'shop@phpmanual.test']);
} finally { restore_error_handler(); }
if ($accepted) { throw new RuntimeException('Ожидался отказ учебного SMTP'); }
file_put_contents(__DIR__ . '/transport-warning.txt', $warning ?? 'Нет предупреждения');
echo "Письмо не принято: проверьте адрес и настройки транспорта\n";
Ожидаемый результат
Письмо не принято: проверьте адрес и настройки транспорта
Письмо не сохранено: SMTP отклонил получателя
Новая пустая папка из этого архива; в первом терминале python smtp_sink.py --reject. Приёмник отвечает 550 на RCPT, файл письма не создаётся. Обработчик E_WARNING установлен только вокруг одного mb_send_mail и обязательно снят в finally. Подробное предупреждение сохраняется для оператора; человек видит понятный отказ. Этот опыт отличается от неизвестного результата после обрыва связи: повтор отправки без идемпотентного события может дать дубликат.
Ошибки и границы. additional_headers принимает массив с 7.2, additional_params nullable с 8.0. PHP проверяет часть недопустимых заголовков/нулевых байтов, но это не замена вашей валидации. Ошибка локального транспорта может дать warning/false; исключения/ошибки вызова также не являются доставкой. Подробности системного mail относятся к отдельной почтовой категории.
Рядом: mb_language, mb_encode_mimeheader, mb_internal_encoding. Байты, кодовые точки и графемы; общие правила вызова.
Источники и обсуждения
- PHP: book.mbstring
- PHP: mbstring.setup
- PHP: mbstring.installation
- PHP: mbstring.configuration
- PHP: mbstring.constants
- PHP: mbstring.encodings
- PHP: mbstring.ja-basic
- PHP: mbstring.http
- PHP: mbstring.supported-encodings
- PHP: mbstring.overload
- PHP: mbstring.php4.req
- PHP: ref.mbstring
- PHP: function.mb-check-encoding
- PHP: function.mb-chr
- PHP: function.mb-convert-case
- PHP: function.mb-convert-encoding
- PHP: function.mb-convert-kana
- PHP: function.mb-convert-variables
- PHP: function.mb-decode-mimeheader
- PHP: function.mb-decode-numericentity
- PHP: function.mb-detect-encoding
- PHP: function.mb-detect-order
- PHP: function.mb-encode-mimeheader
- PHP: function.mb-encode-numericentity
- PHP: function.mb-encoding-aliases
- PHP: function.mb-ereg
- PHP: function.mb-ereg-match
- PHP: function.mb-ereg-replace
- PHP: function.mb-ereg-replace-callback
- PHP: function.mb-ereg-search
- PHP: function.mb-ereg-search-getpos
- PHP: function.mb-ereg-search-getregs
- PHP: function.mb-ereg-search-init
- PHP: function.mb-ereg-search-pos
- PHP: function.mb-ereg-search-regs
- PHP: function.mb-ereg-search-setpos
- PHP: function.mb-eregi
- PHP: function.mb-eregi-replace
- PHP: function.mb-get-info
- PHP: function.mb-http-input
- PHP: function.mb-http-output
- PHP: function.mb-internal-encoding
- PHP: function.mb-language
- PHP: function.mb-lcfirst
- PHP: function.mb-list-encodings
- PHP: function.mb-ltrim
- PHP: function.mb-ord
- PHP: function.mb-output-handler
- PHP: function.mb-parse-str
- PHP: function.mb-preferred-mime-name
- PHP: function.mb-regex-encoding
- PHP: function.mb-regex-set-options
- PHP: function.mb-rtrim
- PHP: function.mb-scrub
- PHP: function.mb-send-mail
- PHP: function.mb-split
- PHP: function.mb-str-pad
- PHP: function.mb-str-split
- PHP: function.mb-strcut
- PHP: function.mb-strimwidth
- PHP: function.mb-stripos
- PHP: function.mb-stristr
- PHP: function.mb-strlen
- PHP: function.mb-strpos
- PHP: function.mb-strrchr
- PHP: function.mb-strrichr
- PHP: function.mb-strripos
- PHP: function.mb-strrpos
- PHP: function.mb-strstr
- PHP: function.mb-strtolower
- PHP: function.mb-strtoupper
- PHP: function.mb-strwidth
- PHP: function.mb-substitute-character
- PHP: function.mb-substr
- PHP: function.mb-substr-count
- PHP: function.mb-trim
- PHP: function.mb-ucfirst
- PHP 8.2: устаревшие псевдокодировки
- PHP 8.5: реализация mbstring
- PHP 8.5: сигнатуры mbstring
- Unicode 17.0
- Обсуждение задачи: Windows-1251 данные внутри UTF-8 сайта — обсуждение проблемы
- Обсуждение задачи: Неудачное исправление испорченных букв заменами — обсуждение проблемы
- Обсуждение задачи: После обновления неверно угадывается кодировка CSV — обсуждение проблемы
- Обсуждение задачи: Лимит знаков в форме и составные emoji — обсуждение проблемы
- Обсуждение задачи: Японский файл с полями фиксированной ширины — обсуждение проблемы
- Обсуждение задачи: Кракозябры в теме письма — обсуждение проблемы
- Обсуждение задачи: mb-функция не найдена после изменения INI — обсуждение проблемы
- Обсуждение задачи: При верхнем регистре ß превращается в SS — обсуждение проблемы
Код и руководство с собой
Скачайте самостоятельные примеры с исходными данными, инструкциями и ожидаемыми результатами. Примеры HTTP и фрагменты для проекта помечены отдельно: им нужно указанное окружение.
Код не исполняется на сайте. Скачайте нужный пример и запускайте его в своём локальном окружении.
Материалы сверены 2026-10-12. Примеры и объяснения написаны для этого руководства; источники и обсуждения доступны в каждой главе.


