Строки Строка (string) — набор символов, в котором символ — то же, что и байт. PHP поддерживает набор только из 256 символов и поэтому внутренне не поддерживает кодировку Unicode. Подробнее об этом рассказывает раздел «Подробные сведения о строковом типе». В 32-битных сборках размер строки (string) ограничивается 2 ГБ — максимум 2 147 483 647 байтов. Синтаксис Строковый литерал определяют четырьмя способами: одинарными кавычками двойными кавычками heredoc-синтаксисом nowdoc-синтаксисом Одинарные кавычки Простейший способ определить строку — заключить строку в одинарные кавычки — символ '. Буквальную одинарную кавычку при записи в строке экранируют обратным слешем — \. Сам обратный слеш дублируют — \\. В остальных случаях обратный слеш в одинарных кавычках обрабатывется как буквальный обратный слеш: PHP не рассматривает последовательности вроде \r или \n в одинарных кавычках как управляющие, а выводит как записали. Переменные и управляющие последовательности служебных символов в одинарных кавычках не обрабатываются, в отличие от синтаксиса двойных кавычек и heredoc. ]]> Двойные кавычки PHP распознает следующие управляющие последовательности служебных символов, если строку заключили в двойные кавычки — ": Управляющие последовательности Последовательность Значение \n новая строка (LF или 0x0A (10) в ASCII) \r возврат каретки (CR или 0x0D (13) в ASCII) \t горизонтальная табуляция (HT или 0x09 (9) в ASCII) \v вертикальная табуляция (VT или 0x0B (11) в ASCII) \e escape-знак (ESC или 0x1B (27) в ASCII) \f подача страницы (FF или 0x0C (12) в ASCII) \\ обратная косая черта \$ знак доллара \" двойная кавычка \[0-7]{1,3} Восьмеричная запись: символ, код которого записали в восьмеричной нотации (т. е. "\101" === "A"), т. е. в виде последовательности символов, которая соответствует регулярному выражению [0-7]{1,3}. В ситуации целочисленного переполнения (если символ не поместится в один байт), старшие биты будут без предупреждения отброшены (т. е. "\400" === "\000") \x[0-9A-Fa-f]{1,2} Шестнадцатеричная система счисления: символ, код которого записали в шестнадцатеричной нотации (т. е. "\x41" === "A"), т. е. в виде последовательности символов, которая соответствует регулярному выражению [0-9A-Fa-f]{1,2} \u{[0-9A-Fa-f]+} Стандарт Unicode: символ, код которого записали в нотации кодовых точек Unicode, т. е. в виде последовательности символов, которая соответствует регулярному выражению [0-9A-Fa-f]+, которые будут отображены как строка в кодировке UTF-8. Последовательность необходимо заключать в фигурные скобки. Например: "\u{41}" === "A"
Как и в строках в одинарных кавычках, экранирование другого символа выведет также и символ обратного слеша. Наиболее важное свойство строк в двойных кавычках состоит в том, что имена переменных в них развёрнутся и обработаются. Подробнее об этом рассказывает раздел «Интерполяция строк».
Heredoc Третий способ определения строк — heredoc-синтаксис: <<<. Следом за этим оператором указывают идентификатор, а затем перевод строки. Затем идёт сама строка, за которой снова идёт тот же идентификатор, чтобы закрыть вставку. Закрывающий идентификатор разрешается отбивать пробелами или символами табуляции, и тогда отступ удалится из каждой строки в блоке документа. До PHP 7.3.0 закрывающий идентификатор указывали в самом начале новой строки. Кроме того, закрывающий идентификатор подчиняется тем же правилам именования, что и другие метки в PHP: содержит только буквенно-цифровые символы и подчёркивания, и не начинается с цифрового символа или символа подчёркивания. Базовый пример heredoc-синтаксиса в PHP 7.3.0 ]]> &example.outputs.73; PHP выбросит исключение ParseError, если закрывающий идентификатор сместили дальше хотя бы одной строки тела: Идентификатору закрытия нельзя отступать дальше строк тела ]]> &example.outputs.73; В теле и перед идентификатором окончания heredoc-блока разрешается делать отступы символами пробелов и табуляции, но нельзя смешивать символы табуляции и пробелы относительно отступа идентификатора закрытия и отступа тела до начала закрывающего идентификатора; heredoc-синтаксис будет работать с отступом перед маркером закрытия, только если каждая строка тела начинается, но не ограничивается, с того же отступа, что и отступ перед маркером закрытия. При несовпадении отступов в начале строк тела с отступом перед идентификатором закрытия PHP выбросит исключение ParseError. Ограничения на пробельные отступы добавили, потому что смешивание табуляций и пробелов для отступов вредно для разбора. Пример несовпадения отступов в теле и перед идентификатором закрытия тела ]]> &example.outputs.73; За идентификатором закрытия строки тела не обязательно ставить точку с запятой или новую строку. Приведём пример кода, который разрешается с PHP 7.3.0: Продолжение выражения после идентификатора закрытия ]]> &example.outputs.73; string(11) "a b c" [1] => string(5) "d e f" } ]]> Парсер примет идентификатор за закрывающий и выбросит исключение ParseError, если найдёт закрывающий идентификатор в начале строки, даже если это часть слова. Закрывающий идентификатор в теле текста провоцирует исключение ParseError ]]> &example.outputs.73; Таких проблем помогает избегать несложное, но надёжное правило: не выбирать идентификатор закрытия, который встречается в теле текста. До PHP 7.3.0 строке с закрывающим идентификатором нельзя было содержать других символов, кроме точки с запятой — ;. То есть идентификатор нельзя вводить с отступом, а пробелы или знаки табуляции нельзя вводить до или после точки с запятой. Учитывают также, что первым символом перед закрывающим идентификатором идёт символ новой строки, который определяет операционная система. Например, в Unix-системах, включая macOS, это символ \n. После идентификатора закрытия должна сразу начинаться новая строка. PHP не будет считать идентификатор закрывающим и продолжит поиск идентификатора, если это правило нарушили и идентификатор закрытия не «чистый». На последней строке возникнет ошибка синтаксического анализа, если PHP так и не найдёт правильный идентификатор закрытия до конца текущего файла. Пример неправильного до PHP 7.3.0 синтаксиса ]]> Пример правильного даже до PHP 7.3.0 синтаксиса ]]> В Heredoc-синтаксисе, который содержит переменные, нельзя инициализировать свойства класса. Heredoc-текст ведёт себя как строка в двойных кавычках, хотя и не заключается в двойные кавычки. То есть в heredoc кавычки не экранируют, но перечисленные управляющие коды по-прежнему разрешено указывать. Переменные разворачиваются, но в выражениях со сложными переменными внутри heredoc работают так же внимательно, как и при работе со строками. Пример определения heredoc-строки foo = 'Foo'; $this->bar = array('Bar1', 'Bar2', 'Bar3'); } } $foo = new foo(); $name = 'Имярек'; echo <<foo. Теперь я вывожу {$foo->bar[1]}. Это должно вывести заглавную букву 'A': \x41 EOT; ?> ]]> &example.outputs; Heredoc-синтаксис разрешён также для передачи данных через аргументы функции: Пример heredoc-синтаксиса с аргументами ]]> В heredoc-синтаксисе разрешено инициализировать статические переменные и свойства или константы класса: Инициализация статических переменных heredoc-синтаксисом ]]> Допустимо также окружать heredoc-идентификатор двойными кавычками: Двойные кавычки в heredoc ]]> Nowdoc Nowdoc — то же для строк в одинарных кавычках, что и heredoc для строк в двойных кавычках. Синтаксис Nowdoc похож на heredoc-синтаксис, но внутри него не выполняются интерполяция строк. Конструкция легко встраивает PHP-код или другие большие блоки текста без предварительного экранирования. В этом он отчасти похож на SGML-конструкцию <![CDATA[ ]]>, в том, что он объявляет блок текста, который не требует обработки. Nowdoc задают той же последовательностью символов <<<, что и в heredoc, но следующий за ней идентификатор берут в одинарные кавычки, например, <<<'EOT'. Условия, которые распространяются на идентификаторы heredoc-синтаксиса, действительны также и для синтаксиса nowdoc, а больше остальных те, что относятся к закрывающему идентификатору. Пример nowdoc-синтаксиса ]]> &example.outputs; Nowdoc с переменными в строках с двойными кавычками foo = 'Foo'; $this->bar = array('Bar1', 'Bar2', 'Bar3'); } } $foo = new foo(); $name = 'Имярек'; echo <<<'EOT' Меня зовут "$name". Я печатаю $foo->foo. Теперь я печатаю {$foo->bar[1]}. Это не должно вывести заглавную 'A': \x41 EOT; ?> ]]> &example.outputs; foo. Теперь я печатаю {$foo->bar[1]}. Это не должно вывести заглавную 'A': \x41]]> Пример со статичными данными ]]> Интерполяция строк PHP умеет подставлять внутри строк значения вместо переменных, если строку (string) указали в двойных кавычках или heredoc-синтаксисом. В PHP предусмотрели два вида синтаксиса для указания переменных в строках: базовый и продвинутый. Базовым синтаксисом пользуются чаще, им легко встраивать переменную, значение массива (array) или свойство объекта (object) с минимумом усилий. Базовый синтаксис PHP интерпретирует как переменную и подставит вместо переменной значение этой переменной, если встретит в строке знак доллара $, за которым идут символы, из которых PHP разрешает составлять название переменной. ]]> &example.outputs; Формально структура базового синтаксиса подстановки переменных выглядит вот так: имя имя-переменной:: $ имя имя:: [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]* ]]> Синтаксис ${ выражение } устарел с PHP 8.2.0, поскольку интерпретируется как переменные переменных: ]]> &example.outputs.82; &example.outputs; Вместо этого пользуются продвинутым синтаксисом интерполяции строк. Знак доллара остается в строке как сам знак доллара, если невозможно сформировать допустимое имя: ]]> &example.outputs; Пример интерполяции значений первого уровня массива или свойства объекта "фиолетового"); echo "Он выпил немного $juices[0] сока."; echo PHP_EOL; echo "Он выпил немного $juices[1] сока."; echo PHP_EOL; echo "Он выпил немного $juices[string_key] сока."; echo PHP_EOL; class A { public $s = "string"; } $o = new A(); echo "Значение свойства объекта: $o->s."; ?> ]]> &example.outputs; Ключ массива указывают без кавычек, поэтому невозможно ссылаться на константу как на ключ в базовом синтаксисе. Вместо этого пользуются продвинутым синтаксисом. В PHP 7.1.0 добавили поддержку отрицательных числовых индексов. Отрицательные числовые индексы ]]> &example.outputs; Для выражений, которые сложнее этих, лучше пользоваться продвинутым синтаксисом. Продвинутый, или фигурный, синтаксис Продвинутый синтаксис разрешает интерполировать переменные с произвольными методами доступа. В строках продвинутым синтаксисом указывают скалярные переменные, элементы массива, статические и динамические свойства объекта со строковым представлением. Выражение записывается как и вне строки, а затем оборачивается в фигурные скобки { и }. Поскольку знак { невозможно экранировать, продвинутый синтаксис распознаётся только тогда, когда знак $ идёт непосредственно за знаком {. Знак доллара экранируют синтаксисом {\$, чтобы получить литерал {$. Поясняющие примеры: 'Индексное значение', 'const-key' => 'Ключ со знаком минуса', 'foo' => ['foo1', 'foo2', 'foo3'] ]; // Не работает, выводит: Это { здорово} echo "Это { $great}"; // Работает, выводит: Это здорово echo "Это {$great}"; class Square { public $width; public function __construct(int $width) { $this->width = $width; } } $square = new Square(5); // Работает echo "Ширина квадрата составляет {$square->width}00 сантиметров."; // Работает, ключи, взятые в кавычки, работают только с синтаксисом фигурных скобок echo "Это работает: {$arr['key']}"; // Работает echo "Это работает: {$arr[3][2]}"; echo "Работает: {$arr[DATA_KEY]}"; // При работе с многомерными массивами массивы внутри строк оборачивают в фигурные скобки echo "Это работает: {$arr['foo'][2]}"; echo "Работает: {$obj->values[3]->name}"; echo "Работает: {$obj->$staticProp}"; // Не работает, выводит: C:\directory\{fantastic}.txt echo "C:\directory\{$great}.txt"; // Работает, выводит: C:\directory\fantastic.txt echo "C:\\directory\\{$great}.txt"; ?> ]]> В строках с продвинутым синтаксисом возможно записывать переменные переменных, поскольку продвинутый синтаксис разрешает произвольные выражения. Доступ к символам и изменение символов в строке Символы внутри строк индексируются с начала строки, индексы начинаются с 0. Смещение символа, который требуется прочитать или изменить внутри строки, указывают после строки в квадратных скобках массива (array), например $str[42]. Для этого о строке думают как о массиве символов. Больше одного символа получают и заменяют функциями substr и substr_replace. Начиная с PHP 7.1.0 поддерживаются отрицательные значения смещения. Они задают смещение с конца строки. Раньше отрицательные смещение вызывали ошибку уровня E_NOTICE при чтении (возвращая пустую строку) или E_WARNING при записи (оставляя строку без изменений). До PHP 8.0.0 доступ к символам в строках (string) получали, указывая фигурные скобки, например $str{42}. Синтаксис фигурных скобок устарел с PHP 7.4.0 и не поддерживается с PHP 8.0.0. Попытка записи в смещение за границами строки дополнит строку пробелами до этого смещения. Нецелочисленные типы преобразуются в целочисленные. Неверный тип смещения выдаст ошибку уровня E_WARNING. При добавлении в смещение строки новых символов присвоится только первый символ (байт). Начиная с PHP 7.1.0 присваивание пустой строки вызовет фатальную ошибку. Раньше присваивался нулевой байт (NULL). Внутренне PHP представляет строки массивами байтов. Поэтому доступ или изменение строки по смещению небезопасны для многобайтовых данных и выполняются только со строками в однобайтовых кодировках, например ISO-8859-1. Начиная с PHP 7.1.0 попытка указать оператор пустого индекса на пустой строке выдаст фатальную ошибку. Раньше пустая строка преобразовывалась в массив без предупреждения. Примеры строк ]]> Смещение в строке задают либо целым числом, либо целочисленной строкой, иначе PHP выдаст предупреждение. Пример недопустимого смещения строки ]]> &example.outputs; Доступ к переменным других типов, кроме массивов и объектов, которые реализуют соответствующие интерфейсы, через операторы [] или {} без предупреждения возвращает &null;. Доступ к символам в строковых литералах получают через операторы [] или {}. Доступ к символам в строковых литералах через оператор {} объявили устаревшим в PHP 7.4 и удалили в PHP 8.0.
Полезные функции и операторы Строки объединяют оператором «.» — точки. Обратите внимание, оператор сложения «+» здесь не работает. Подробнее об этом рассказано в разделе «Строковые операторы». В языке предусмотрели ряд полезных функций для манипулирования строками. Общие функции описывает раздел «Функции для работы со строками», а для расширенного поиска и замены — «Функции Perl-совместимых регулярных выражений». В PHP также предусмотрели функции для работы с URL-адресами и функции шифрования или дешифрования строк (Sodium и Hash). Наконец, смотрите также функции символьных типов. Преобразование в строку Значение преобразовывают в строку приведением через оператор (string) или функцией strval. В выражениях, в которых требуется строка, преобразование выполняется автоматически. Это выполняется во время вывода через языковые конструкции echo или print, либо когда значение переменной сравнивается со строкой. Разделы руководства «Типы» и «Манипуляции с типами», прояснят сказанное ниже. Смотрите также описание функции settype. Значение bool &true; преобразовывается в строку «1», а логическое значение &false; преобразовывается в «» (пустую строку). Такое поведение допускает преобразование значения в обе стороны — из логического типа в строковый и наоборот. Целое число (int) или число с плавающей точкой (float) преобразовывается в строку, которая будет представлять число в текстовом виде (включая экспоненциальную часть для чисел с плавающей точкой). Большие числа с плавающей точкой преобразовываются в экспоненциальную запись (4.1E+6). Начиная с PHP 8.0.0 в качестве разделителя дробной части в числах с плавающей точкой разрешено использовать только точку («.»). До PHP 8.0.0 символ десятичной точки определялся в настройках языкового стандарта скрипта (категория LC_NUMERIC). Смотрите функцию setlocale. Массивы преобразовываются в строку «Array». Поэтому конструкции echo или print не умеют без помощи функций отображать содержимое массива (array). Чтобы просмотреть отдельный элемент, пользуются синтаксисом echo $arr['foo']. Ниже рассказывается об отображении или просмотре всего содержимого. Для преобразования объекта (object) в строку (string) определяют магический метод __toString. Ресурс (resource) преобразовывается в строку (string) вида «Resource id #1», где 1 — это номер ресурса, который PHP назначает ресурсу (resource) во время исполнения кода. И хотя она уникальна для текущего запуска скрипта (т. е. веб-запроса или CLI-процесса) и не будет использована повторно для этого ресурса, не стоит полагаться на эту строку, потому что её могут изменить в будущем. Тип ресурса можно получить вызовом функции get_resource_type. Значение &null; всегда преобразовывается в пустую строку. Как указано выше, прямое преобразование в строку массивов, объектов или ресурсов не даёт полезной информации о значении, кроме типа. Более эффективные инструменты вывода значений для отладки этих типов — это функции print_r и var_dump. Бо́льшая часть значений в PHP преобразуема в строку для постоянного хранения. Этот метод преобразования называется сериализацией. Сериализуют значения функцией serialize. Подробные сведения о строковом типе Строковый тип (string) в PHP реализовали в виде массива байтов и целочисленного значения, которое содержит длину буфера. В этой структуре нет информации о том, как преобразовывать байты в символы, эту задачу решает программист. Нет ограничений на значения, из которых состоит строка, например, байт со значением 0 (NUL-байт) разрешается где угодно в строке (однако рекомендуют учитывать, что ряд функций, которые в этом руководстве назвали «бинарно небезопасными», передают строки библиотекам, которые игнорируют данные после NUL-байта). Такая природа строкового типа объясняет, почему в PHP нет отдельного типа «byte» — строки выполняют эту роль. Функции, которые не возвращают текстовых данных, — например, произвольный поток данных, считываемый из сетевого сокета, — по-прежнему возвращают строки. С учётом того, что PHP не диктует конкретную кодировку для строк, может возникнуть вопрос: Как тогда кодируются строковые литералы? Например, строка «á» эквивалентна «\xE1» (ISO-8859-1), «\xC3\xA1» (UTF-8, форма нормализации C), «\x61\xCC\x81» (UTF-8, форма нормализации D) или другому возможному представлению? Ответ такой: строка будет закодирована способом, которым она закодирована в файле скрипта. Поэтому, если скрипт записан в кодировке ISO-8859-1, то и строка будет закодирована в ISO-8859-1 и т. д. Однако это правило не выполняется при включённом режиме Zend Multibyte: скрипт записывают в произвольной кодировке, объявляя её или полагаясь на автоопределение, а затем конвертируют в конкретную внутреннюю кодировку, которая и будет использована для строковых литералов. Учтите, что на кодировку скрипта (или на внутреннюю кодировку, если включён режим Zend Multibyte) накладывается ряд ограничений: почти в каждом случае эта кодировка должна быть надмножеством кодировки ASCII, например, UTF-8 или ISO-8859-1. Учтите также, что кодировки, зависящие от состояния, где одни и те же значения байтов допустимы в начальном и не начальном состоянии сдвига, создают риск проблем. Строковые функции, чтобы быть полезными, пробуют предположить кодировку строки. Единство в этом вопросе не помешало бы, но PHP-функции работают с текстом по-разному: Одни — предполагают, что строка закодирована в какой-то однобайтовой кодировке, но для корректной работы им не нужно интерпретировать байты как конкретные символы. Сюда попадают функции вроде substr, strpos, strlen и strcmp. Другой способ мышления об этих функциях — представлять, что они оперируют буферами памяти, т. е. работают непосредственно с байтами и их смещениями. Другим — передаётся кодировка строки или они принимают значение по умолчанию, если кодировку не передали. Это относится к функции htmlentities и большей части функций модуля mbstring. Третьи — работают с текущими настройками локали (смотрите setlocale), но оперируют побайтово. Наконец четвёртые — предполагают, что строка использует конкретную кодировку, обычно UTF-8. Сюда попадает бо́льшая часть функций из модулей intl и PCRE (для последнего — только при указании модификатора u). В конечном счёте, программа будет работать с кодировкой Unicode правильно, если старательно избегать функций, которые не будут работать с Unicode-строками или повредят данные, и вызывать вместо них те, которые ведут себя корректно, обычно это функции из модулей intl и mbstring. Однако работа с функциями, которые умеют обрабатывать Unicode, — это только начало. Независимо от того, какие функции предлагает язык, рекомендовано знать спецификацию Unicode. Например, программа, которая предполагает существование только прописных и строчных букв, делает неверное предположение.