Урок по треку PHP 6 мин

Строки в PHP и UTF-8

Байты и UTF-8, mb-функции, интерполяция, heredoc, полезные функции PHP 8.

Строка в PHP это последовательность байтов без знания о кодировке. Отсюда главный вопрос собеса: почему strlen("привет") равно 12 и как работать с UTF-8.

Байты и символы

strlen("привет");        // 12: в UTF-8 кириллица по 2 байта
mb_strlen("привет");     // 6
substr("Ёжик", 0, 3);    // битая строка: полтора символа
mb_substr("Ёжик", 0, 3); // "Ёжи"
strtoupper("ёж");        // "ёж": с PHP 8.2 меняет только ASCII
mb_strtoupper("ёж");     // "ЁЖ"

Для пользовательского текста используйте mb_*: mb_strlen, mb_substr, mb_strtolower, mb_str_split. В регулярных выражениях модификатор u: preg_match('/^\p{L}+$/u', $name).

Кавычки, heredoc и nowdoc

  • 'текст $x': буквально, только \' и \\.
  • "текст $x\n": подстановка переменных и escape-последовательности.
  • "{$user['name']}", "{$obj->prop}": сложные выражения в фигурных скобках.
  • heredoc <<<EOT ведёт себя как двойные кавычки, nowdoc <<<'EOT' как одинарные.

Поиск

Классическая ловушка:

if (!strpos($s, "a")) { ... } // неверно, если "a" в позиции 0
if (strpos($s, "a") === false) { ... }
if (!str_contains($s, "a")) { ... } // PHP 8.0

Есть ещё str_starts_with и str_ends_with. Они возвращают bool и не страдают от позиции 0.

Разбиение и сборка

explode(",", "a,,b,");      // ["a", "", "b", ""]: пустые элементы остаются
implode(", ", $names);
preg_split('/\s+/', trim($text));
str_pad("7", 3, "0", STR_PAD_LEFT); // "007"
sprintf("%05.2f", 3.14159);          // "03.14"
number_format(1234.5, 2, ".", " "); // "1 234.50"

Сравнение без учёта регистра

strcasecmp и strtolower работают по ASCII. Для кириллицы mb_strtolower($a) === mb_strtolower($b), для сортировки по правилам языка Collator из intl.

Как PHP хранит строки

zend_string хранит длину, хеш и счётчик ссылок. Присваивание не копирует данные (copy-on-write), литералы интернируются. Склейка .= в цикле обычно недорога, но гигабайтный файл через file_get_contents упрётся в memory_limit: большие данные читают потоково (fgets, SplFileObject, генераторы).

Экранирование по контексту

  • HTML: htmlspecialchars($s, ENT_QUOTES, 'UTF-8').
  • URL: rawurlencode, http_build_query.
  • Shell: escapeshellarg.
  • SQL: только подготовленные запросы.

Частые ошибки

  • strlen, substr, ucfirst для кириллицы.
  • strpos(...) == false.
  • explode и ожидание, что пустых элементов не будет.
  • Регулярки без u для UTF-8.

Что спросят на собесе

  • Почему strlen для кириллицы возвращает больше, чем символов?
  • Чем одинарные кавычки отличаются от двойных, heredoc от nowdoc?
  • В чём ловушка strpos и что появилось в PHP 8?
  • Как правильно экранировать строку для HTML, URL и shell?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.