Строки Строка (string) — набор символов. Каждый байт строки интерпретируется как один символ. PHP поддерживает набор только из 256 символов и поэтому внутренне не поддерживает кодировку Unicode. Подробнее об этом рассказывает раздел «Подробные сведения о строковом типе». В 32-битных сборках размер строки (string) ограничивается 2 ГБ — максимум 2 147 483 647 байтов. Синтаксис Строковый литерал определяют четырьмя способами: одинарными кавычками двойными кавычками heredoc-синтаксисом nowdoc-синтаксисом Одинарные кавычки Простейший способ определить строку — заключить строку в одинарные кавычки — символ '. Буквальную одинарную кавычку при записи в строке экранируют обратным слешем — \. Сам обратный слеш дублируют — \\. В остальных случаях обратный слеш в одинарных кавычках обрабатывется как буквальный обратный слеш: PHP не рассматривает последовательности вроде \r или \n в одинарных кавычках как управляющие, а выводит как записали. Переменные и управляющие последовательности служебных символов в одинарных кавычках не обрабатываются, в отличие от синтаксиса двойных кавычек и heredoc. Виды синтаксиса ]]> Двойные кавычки В строке в двойных кавычках — " — PHP распознает следующие управляющие последовательности служебных символов: Управляющие последовательности Последовательность Значение \n Перевод строки. В кодировке ASCII управляющий символ обозначается аббревиатурой LF и соответствует коду 0x0A в шестнадцатеричной или 10 в десятичной нотации \r Возврат каретки. В кодировке ASCII управляющий символ обозначается аббревиатурой CR и соответствует коду 0x0D в шестнадцатеричной или 13 в десятичной нотации \t Горизонтальная табуляция. В кодировке ASCII этот управляющий символ обозначается аббревиатурой HT и соответствует коду 0x09 в шестнадцатеричной или 9 в десятичной нотации \v Вертикальная табуляция. В кодировке ASCII этот управляющий символ обозначается аббревиатурой VT и соответствует коду 0x0B в шестнадцатеричной или 11 в десятичной нотации \e Escape-символ. В кодировке ASCII этот управляющий символ обозначается аббревиатурой HT и соответствует коду 0x1B в шестнадцатеричной или 27 в десятичной нотации \f Подача страницы. В кодировке ASCII этот управляющий символ обозначается аббревиатурой HT и соответствует коду 0x0C в шестнадцатеричной или 12 в десятичной нотации \\ Обратный слеш \$ Знак доллара \" Двойная кавычка \[0-7]{1,3} Восьмеричная запись: последовательность символов, которая соответствует регулярному выражению [0-7]{1,3}, — "\101" === "A". При целочисленном переполнении, когда символ не помещается в один байт, старшие биты без предупреждения отбрасываются: "\400" === "\000" \x[0-9A-Fa-f]{1,2} Шестнадцатеричная запись: последовательность символов, которая соответствует регулярному выражению [0-9A-Fa-f]{1,2}, — "\x41" === "A" \u{[0-9A-Fa-f]+} Символы Юникода: последовательность символов, которая соответствует регулярному выражению [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 интерпретирует как переменную и подставит вместо переменной значение этой переменной, если встретит в строке знак доллара $, за которым идут символы, допустимые для составления названий переменных. Интерполяция строк ]]> &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 выдаст предупреждение. Пример недопустимого смещения строки getMessage(), PHP_EOL; } echo PHP_EOL; } ?> ]]> &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. Например, программа, которая предполагает существование только прописных и строчных букв, делает неверное предположение.