Строки Строка (string) — это набор символов, в котором символ — то же, что и байт. То есть PHP поддерживает набор только из 256 символов и, следовательно, не обеспечивает встроенную поддержку кодировки Unicode. Подробнее об этом рассказывает раздел «Подробные сведения о строковом типе». В 32-битных сборках размер строки (string) ограничен 2 ГБ (2 147 483 647 байтов максимум). Синтаксис Строковый литерал определяют четырьмя способами: одинарными кавычками двойными кавычками heredoc-синтаксисом nowdoc-синтаксисом Одинарные кавычки Простейший способ определить строку — заключить строку в одинарные кавычки (символ '). Чтобы записать внутри строки буквальную одинарную кавычку, её экранируют обратным слешем (\). Чтобы записать сам обратный слеш, его дублируют (\\). В остальных случаях обратный слеш будет обработан как буквальный обратный слеш: то есть последовательности вроде \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; Если закрывающий идентификатор смещён дальше хотя бы одной строки тела, будет выброшено исключение ParseError: Отступу закрывающего идентификатора нельзя отступать больше, чем другим строкам тела &example.outputs.73; В теле тоже будет допустимо указывать табуляции, если закрывающий идентификатор отбить отступом. Однако табуляциям и пробелам не разрешено смешиваться относительно отступа закрывающего идентификатора и тела (вплоть до закрывающего идентификатора). В каждом из этих случаев будет выброшено исключение 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 обрабатывает переменные внутри строки, если строку указали в двойных кавычках или heredoc-синтаксисом. В PHP предусмотрели два вида синтаксиса для указания переменных в строках: простой и сложный. Простым синтаксисом пользуются чаще, с ним легко встраивать переменную, значение массива (array) или свойство объекта (object) с минимумом усилий. Сложный синтаксис легко определить по фигурным скобкам, которые окружают выражение. Простой синтаксис Если интерпретатор встречает знак доллара ($), он захватывает как можно больше символов, чтобы сформировать правильное имя переменной. Имя переменной берут в фигурные скобки, если нужно точно определить конец имени. ]]> &example.outputs; Аналогично будет проанализирован индекс массива (array) или свойство объекта (object). В индексах массива закрывающая квадратная скобка (]) означает конец определения индекса. На свойства объекта распространяются те же правила, что и на простые переменные. Пример простого синтаксиса "purple"); echo "He drank some $juices[0] juice.".PHP_EOL; echo "He drank some $juices[1] juice.".PHP_EOL; echo "He drank some $juices[koolaid1] juice.".PHP_EOL; class people { public $john = "John Smith"; public $jane = "Jane Smith"; public $robert = "Robert Paulsen"; public $smith = "Smith"; } $people = new people(); echo "$people->john drank some $juices[0] juice.".PHP_EOL; echo "$people->john then said hello to $people->jane.".PHP_EOL; echo "$people->john's wife greeted $people->robert.".PHP_EOL; echo "$people->robert greeted the two $people->smiths."; // Не сработает ?> ]]> &example.outputs; В PHP 7.1.0 добавлена поддержка отрицательных числовых индексов. Отрицательные числовые индексы ]]> &example.outputs; Для выражений, которые сложнее этих, лучше пользоваться сложным синтаксисом. Сложный (фигурный) синтаксис Он называется сложным не из-за сложности синтаксиса, а только потому, что разрешает писать сложные выражения. Скалярная переменная, элемент массива или отображаемое в строку свойство объекта разрешено указывать в строке этим синтаксисом. Выражение записывается как и вне строки, а затем берётся в фигурные скобки: { и }. Поскольку знак { невозможно экранировать, этот синтаксис будет распознаваться только тогда, когда знак $ идёт непосредственно за знаком {. Чтобы получить литерал {$, знак доллара экранируют {\$. Поясняющие примеры: width}00 сантиметров."; // Работает, ключи, взятые в кавычки, работают только с синтаксисом фигурных скобок echo "Это работает: {$arr['key']}"; // Работает echo "Это работает: {$arr[4][3]}"; // Следующая запись неверна по той же причине, по которой запись $foo[bar] неверна вне строки. // Сначала PHP ищет константу foo и выбрасывает ошибку, если не находит. // PHP, если найдёт константу, будет использовать как индекс массива // значение константы, а не само «foo» echo "Это неправильно: {$arr[foo][3]}"; // Работает. При обращении к многомерным массивам внутри // строк указывают фигурные скобки echo "Это работает: {$arr['foo'][3]}"; // Работает. echo "Это работает: " . $arr['foo'][3]; echo "Это тоже работает: {$obj->values[3]->name}"; echo "Это значение переменной с именем $name: {${$name}}"; echo "Это значение переменной с именем, которое возвращает функция getName(): {${getName()}}"; echo "Это значение переменной с именем, которое возвращает \$object->getName(): {${$object->getName()}}"; // Не работает, выводит: Это то, что возвращает функция getName(): {getName()} echo "Это то, что возвращает функция getName(): {getName()}"; // Не работает, выводит: C:\folder\{fantastic}.txt echo "C:\folder\{$great}.txt" // Работает, выводит: C:\folder\fantastic.txt echo "C:\\folder\\{$great}.txt" ?> ]]> Через переменные внутри строк, которые записали таким синтаксисом, доступны свойства класса. $bar}\n"; echo "{$foo->{$baz[1]}}\n"; ?> ]]> &example.outputs; Значение внутри литерала {$}, к которому получают доступ из функций, вызовов методов, статических переменных класса и констант класса, интерпретируется как имя переменной в области, в которой определена строка. Синтаксис одинарных фигурных скобок ({}) не будет работать для доступа к значениям функций, методов, констант классов или статических переменных класса. ]]> Доступ и изменение символа в строке Чтобы получить доступ и изменить символ в строке, нужно в квадратных скобках после переменной определить смещение искомого символа относительно начала строки начиная с нуля, например, $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-совместимых регулярных выражений». Предусмотрены также функции для работы с 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. Например, программа, которая предполагает существование только прописных и строчных букв, делает неверное предположение.