mirror of
https://github.com/php/doc-ru.git
synced 2025-08-16 18:22:04 +00:00
1443 lines
57 KiB
XML
1443 lines
57 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: ef5a00895dbb9a3abbe3edc03d1f966b239a2eb2 Maintainer: rjhdby Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<sect1 xml:id="language.types.string">
|
||
<title>Строки</title>
|
||
|
||
<para>
|
||
Строка (<type>string</type>) — набор символов, в котором символ — то же,
|
||
что и байт. PHP поддерживает набор только из 256 символов и поэтому
|
||
внутренне не поддерживает кодировку Unicode. Подробнее об этом рассказывает раздел
|
||
«<link linkend="language.types.string.details">Подробные сведения о строковом типе</link>».
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
В 32-битных сборках размер строки (<type>string</type>) ограничивается 2 ГБ — максимум 2 147 483 647 байтов.
|
||
</simpara>
|
||
</note>
|
||
|
||
<sect2 xml:id="language.types.string.syntax">
|
||
<title>Синтаксис</title>
|
||
|
||
<para>
|
||
Строковый литерал определяют четырьмя способами:
|
||
</para>
|
||
|
||
<itemizedlist>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.types.string.syntax.single">одинарными кавычками</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.types.string.syntax.double">двойными кавычками</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.types.string.syntax.heredoc">heredoc-синтаксисом</link>
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
<link linkend="language.types.string.syntax.nowdoc">nowdoc-синтаксисом</link>
|
||
</simpara>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<sect3 xml:id="language.types.string.syntax.single">
|
||
<title>Одинарные кавычки</title>
|
||
|
||
<para>
|
||
Простейший способ определить строку — заключить строку в одинарные кавычки —
|
||
символ <literal>'</literal>.
|
||
</para>
|
||
|
||
<para>
|
||
Буквальную одинарную кавычку при записи в строке экранируют обратным
|
||
слешем — <literal>\</literal>. Сам обратный слеш дублируют —
|
||
<literal>\\</literal>. В остальных случаях обратный слеш в одинарных кавычках
|
||
обрабатывется как буквальный обратный слеш: PHP не рассматривает последовательности
|
||
вроде <literal>\r</literal> или <literal>\n</literal> в одинарных кавычках как управляющие,
|
||
а выводит как записали.
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
<link linkend="language.variables">Переменные</link> и управляющие последовательности
|
||
служебных символов в одинарных кавычках <emphasis>не</emphasis> обрабатываются,
|
||
в отличие от синтаксиса <link linkend="language.types.string.syntax.double">двойных кавычек</link>
|
||
и <link linkend="language.types.string.syntax.heredoc">heredoc</link>.
|
||
</simpara>
|
||
</note>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo 'Это — простая строка';
|
||
|
||
echo 'В строки также разрешено вставлять
|
||
символ новой строки, способом, которым записан этот текст, —
|
||
так делать нормально';
|
||
|
||
// Выводит: Однажды Арнольд сказал: "I'll be back"
|
||
echo 'Однажды Арнольд сказал: "I\'ll be back"';
|
||
|
||
// Выводит: Вы удалили C:\*.*?
|
||
echo 'Вы удалили C:\\*.*?';
|
||
|
||
// Выводит: Вы удалили C:\*.*?
|
||
echo 'Вы удалили C:\*.*?';
|
||
|
||
// Выводит: Это не будет развёрнуто: \n в новую строку
|
||
echo 'Это не будет развёрнуто: \n в новую строку';
|
||
|
||
// Выводит: Переменные $expand и $either также не разворачиваются
|
||
echo 'Переменные $expand и $either также не разворачиваются';
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
</sect3>
|
||
|
||
<sect3 xml:id="language.types.string.syntax.double">
|
||
<title>Двойные кавычки</title>
|
||
|
||
<para>
|
||
PHP распознает следующие управляющие последовательности служебных символов,
|
||
если строку заключили в двойные кавычки — <literal>"</literal>:
|
||
</para>
|
||
|
||
<table>
|
||
<title>Управляющие последовательности</title>
|
||
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>Последовательность</entry>
|
||
<entry>Значение</entry>
|
||
</row>
|
||
</thead>
|
||
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>\n</literal></entry>
|
||
<entry>новая строка (LF или 0x0A (10) в ASCII)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\r</literal></entry>
|
||
<entry>возврат каретки (CR или 0x0D (13) в ASCII)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\t</literal></entry>
|
||
<entry>горизонтальная табуляция (HT или 0x09 (9) в ASCII)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\v</literal></entry>
|
||
<entry>вертикальная табуляция (VT или 0x0B (11) в ASCII)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\e</literal></entry>
|
||
<entry>escape-знак (ESC или 0x1B (27) в ASCII)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\f</literal></entry>
|
||
<entry>подача страницы (FF или 0x0C (12) в ASCII)</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\\</literal></entry>
|
||
<entry>обратная косая черта</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\$</literal></entry>
|
||
<entry>знак доллара</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\"</literal></entry>
|
||
<entry>двойная кавычка</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\[0-7]{1,3}</literal></entry>
|
||
<entry>
|
||
Восьмеричная запись: символ, код которого записали в восьмеричной нотации (т. е. <literal>"\101" === "A"</literal>),
|
||
т. е. в виде последовательности символов, которая соответствует регулярному выражению <literal>[0-7]{1,3}</literal>.
|
||
В ситуации целочисленного переполнения (если символ не поместится в один байт),
|
||
старшие биты будут без предупреждения отброшены (т. е. <literal>"\400" === "\000"</literal>)
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\x[0-9A-Fa-f]{1,2}</literal></entry>
|
||
<entry>
|
||
Шестнадцатеричная система счисления: символ, код которого записали
|
||
в шестнадцатеричной нотации (т. е. <literal>"\x41" === "A"</literal>),
|
||
т. е. в виде последовательности символов, которая соответствует
|
||
регулярному выражению <literal>[0-9A-Fa-f]{1,2}</literal>
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>\u{[0-9A-Fa-f]+}</literal></entry>
|
||
<entry>
|
||
Стандарт Unicode: символ, код которого записали в нотации кодовых точек Unicode,
|
||
т. е. в виде последовательности символов, которая соответствует
|
||
регулярному выражению <literal>[0-9A-Fa-f]+</literal>,
|
||
которые будут отображены как строка в кодировке UTF-8.
|
||
Последовательность необходимо заключать в фигурные скобки.
|
||
Например: <literal>"\u{41}" === "A"</literal>
|
||
</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
|
||
<para>
|
||
Как и в строках в одинарных кавычках, экранирование другого символа
|
||
выведет также и символ обратного слеша.
|
||
</para>
|
||
|
||
<para>
|
||
Наиболее важное свойство строк в двойных кавычках состоит в том,
|
||
что имена переменных в них развёрнутся и обработаются.
|
||
Подробнее об этом рассказывает раздел
|
||
«<link linkend="language.types.string.parsing">Интерполяция строк</link>».
|
||
</para>
|
||
</sect3>
|
||
|
||
<sect3 xml:id="language.types.string.syntax.heredoc">
|
||
<title>Heredoc</title>
|
||
|
||
<simpara>
|
||
Третий способ определения строк — heredoc-синтаксис:
|
||
<literal><<<</literal>. Следом за этим оператором указывают идентификатор,
|
||
а затем перевод строки. Затем идёт сама строка, за которой снова идёт тот же идентификатор,
|
||
чтобы закрыть вставку.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Закрывающий идентификатор разрешается отбивать пробелами или символами табуляции,
|
||
и тогда отступ удалится из каждой строки в блоке документа. До PHP 7.3.0
|
||
закрывающий идентификатор указывали <emphasis>в самом начале</emphasis> новой строки.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Кроме того, закрывающий идентификатор подчиняется тем же правилам именования,
|
||
что и другие метки в PHP: содержит только буквенно-цифровые символы
|
||
и подчёркивания, и не начинается с цифрового символа или символа подчёркивания.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Базовый пример heredoc-синтаксиса в PHP 7.3.0</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
// Без отступа перед маркером закрытия
|
||
echo <<<END
|
||
a
|
||
b
|
||
c
|
||
\n
|
||
END;
|
||
|
||
// Отступ в 4 пробела перед маркером закрытия
|
||
echo <<<END
|
||
a
|
||
b
|
||
c
|
||
END;
|
||
|
||
?>
|
||
]]>
|
||
|
||
</programlisting>
|
||
&example.outputs.73;
|
||
<screen>
|
||
<![CDATA[
|
||
a
|
||
b
|
||
c
|
||
|
||
a
|
||
b
|
||
c
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<simpara>
|
||
PHP выбросит исключение <classname>ParseError</classname>,
|
||
если закрывающий идентификатор сместили дальше хотя бы одной строки тела:
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Идентификатору закрытия нельзя отступать дальше строк тела</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo <<<END
|
||
a
|
||
b
|
||
c
|
||
END;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs.73;
|
||
<screen>
|
||
<![CDATA[
|
||
PHP Parse error: Invalid body indentation level (expecting an indentation level of at least 3) in example.php on line 4
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<simpara>
|
||
В теле и перед идентификатором окончания heredoc-блока разрешается делать отступы
|
||
символами пробелов и табуляции, но <emphasis>нельзя</emphasis> смешивать символы
|
||
табуляции и пробелы относительно отступа идентификатора закрытия и отступа тела
|
||
до начала закрывающего идентификатора; heredoc-синтаксис будет работать с отступом перед маркером закрытия,
|
||
только если каждая строка тела начинается, но не ограничивается, с того же отступа,
|
||
что и отступ перед маркером закрытия. При несовпадении отступов в начале строк тела с отступом
|
||
перед идентификатором закрытия PHP выбросит исключение <classname>ParseError</classname>.
|
||
|
||
Ограничения на пробельные отступы добавили, потому что смешивание табуляций
|
||
и пробелов для отступов вредно для разбора.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Пример несовпадения отступов в теле и перед идентификатором закрытия тела</title>
|
||
<programlisting role="php">
|
||
<!-- Не исправляйте отсутпы в примере:
|
||
они выглядят как пробелы, но часть символов — пробельные (0x0032), часть — символы табуляции (0x0009)!
|
||
Символьный состав отступов тела и маркера окончания описывается глазами читателя; в первом примере
|
||
в теле в действительности 1 таб + 1 пробел, но для читателя это 5 пробелов -->
|
||
<![CDATA[
|
||
<?php
|
||
|
||
/**
|
||
* Каждый следующий пример кода не работает
|
||
*/
|
||
|
||
// Отступ тела отличается от отступа маркера окончания:
|
||
// тело — 5 пробелов, маркер окончания — 2 символа табуляции
|
||
{
|
||
echo <<<END
|
||
a
|
||
END;
|
||
}
|
||
|
||
// Смешивание пробелов и табуляций в теле:
|
||
// тело — 4 пробела + 1 символ табуляции, маркер окончания — 5 пробелов
|
||
{
|
||
echo <<<END
|
||
a
|
||
END;
|
||
}
|
||
|
||
// Смешивание пробелов и табуляций в маркере окончания:
|
||
// тело — 10 пробелов, маркер окончания — 2 символа табуляции + 1 пробел
|
||
{
|
||
echo <<<END
|
||
a
|
||
END;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs.73;
|
||
<screen>
|
||
<![CDATA[
|
||
PHP Parse error: Invalid indentation - tabs and spaces cannot be mixed in example.php line 8
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<simpara>
|
||
За идентификатором закрытия строки тела не обязательно ставить точку с запятой
|
||
или новую строку. Приведём пример кода, который разрешается с PHP 7.3.0:
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Продолжение выражения после идентификатора закрытия</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$values = [<<<END
|
||
a
|
||
b
|
||
c
|
||
END, 'd e f'];
|
||
var_dump($values);
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs.73;
|
||
<screen>
|
||
<![CDATA[
|
||
array(2) {
|
||
[0] =>
|
||
string(11) "a
|
||
b
|
||
c"
|
||
[1] =>
|
||
string(5) "d e f"
|
||
}
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Парсер примет идентификатор за закрывающий и выбросит
|
||
исключение <classname>ParseError</classname>, если найдёт
|
||
закрывающий идентификатор в начале строки, даже если это часть слова.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Закрывающий идентификатор в теле текста провоцирует исключение ParseError</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$values = [<<<END
|
||
a
|
||
b
|
||
END ING
|
||
END, 'd e f'];
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs.73;
|
||
<screen>
|
||
<![CDATA[
|
||
PHP Parse error: syntax error, unexpected identifier "ING", expecting "]" in example.php on line 6
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<simpara>
|
||
Таких проблем помогает избегать несложное, но надёжное правило:
|
||
<emphasis>не выбирать идентификатор закрытия, который встречается в теле текста</emphasis>.
|
||
</simpara>
|
||
|
||
</warning>
|
||
|
||
<warning>
|
||
<simpara>
|
||
До PHP 7.3.0 строке с закрывающим идентификатором нельзя было содержать
|
||
других символов, кроме точки с запятой — <literal>;</literal>. То есть
|
||
идентификатор <emphasis>нельзя вводить с отступом</emphasis>,
|
||
а пробелы или знаки табуляции нельзя вводить до или после точки с запятой.
|
||
Учитывают также, что первым символом перед закрывающим идентификатором идёт
|
||
символ новой строки, который определяет операционная система. Например,
|
||
в Unix-системах, включая macOS, это символ <literal>\n</literal>. После идентификатора
|
||
закрытия должна сразу начинаться новая строка.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
PHP не будет считать идентификатор закрывающим и продолжит поиск идентификатора,
|
||
если это правило нарушили и идентификатор закрытия не «чистый».
|
||
На последней строке возникнет ошибка синтаксического анализа, если PHP
|
||
так и не найдёт правильный идентификатор закрытия до конца текущего файла.
|
||
</simpara>
|
||
|
||
<example>
|
||
<title>Пример неправильного до PHP 7.3.0 синтаксиса</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class foo {
|
||
public $bar = <<<EOT
|
||
bar
|
||
EOT;
|
||
// Отступ перед закрывающим идентификатором недопустим
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<example>
|
||
<title>Пример правильного даже до PHP 7.3.0 синтаксиса</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class foo
|
||
{
|
||
public $bar = <<<EOT
|
||
bar
|
||
EOT;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
<para>
|
||
В Heredoc-синтаксисе, который содержит переменные, нельзя инициализировать свойства класса.
|
||
</para>
|
||
|
||
</warning>
|
||
|
||
<para>
|
||
Heredoc-текст ведёт себя как строка в двойных кавычках, хотя и не заключается в двойные кавычки.
|
||
То есть в heredoc кавычки не экранируют,
|
||
но перечисленные управляющие коды по-прежнему разрешено указывать.
|
||
Переменные разворачиваются, но в выражениях со сложными переменными внутри heredoc
|
||
работают так же внимательно, как и при работе со строками.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Пример определения heredoc-строки</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$str = <<<EOD
|
||
Пример строки,
|
||
которую записали heredoc-синтаксисом
|
||
в несколько строк.
|
||
EOD;
|
||
|
||
/* Более сложный пример с переменными. */
|
||
class foo
|
||
{
|
||
var $foo;
|
||
var $bar;
|
||
|
||
function __construct()
|
||
{
|
||
$this->foo = 'Foo';
|
||
$this->bar = array('Bar1', 'Bar2', 'Bar3');
|
||
}
|
||
}
|
||
|
||
$foo = new foo();
|
||
$name = 'Имярек';
|
||
|
||
echo <<<EOT
|
||
Меня зовут "$name". Я печатаю $foo->foo.
|
||
Теперь я вывожу {$foo->bar[1]}.
|
||
Это должно вывести заглавную букву 'A': \x41
|
||
EOT;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Меня зовут "Имярек". Я печатаю Foo.
|
||
Теперь, я вывожу Bar2.
|
||
Это должно вывести заглавную букву 'A': A]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<para>
|
||
Heredoc-синтаксис разрешён также для передачи данных через аргументы функции:
|
||
</para>
|
||
|
||
<example>
|
||
<title>Пример heredoc-синтаксиса с аргументами</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
var_dump(array(<<<EOD
|
||
foobar!
|
||
EOD
|
||
));
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
В heredoc-синтаксисе разрешено инициализировать статические переменные и свойства или константы класса:
|
||
</para>
|
||
|
||
<example>
|
||
<title>Инициализация статических переменных heredoc-синтаксисом</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
// Статические переменные
|
||
function foo()
|
||
{
|
||
static $bar = <<<LABEL
|
||
Здесь ничего нет...
|
||
LABEL;
|
||
}
|
||
|
||
// Константы/свойства класса
|
||
class foo
|
||
{
|
||
const BAR = <<<FOOBAR
|
||
Пример использования константы
|
||
FOOBAR;
|
||
|
||
public $baz = <<<FOOBAR
|
||
Пример использования поля
|
||
FOOBAR;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
Допустимо также окружать heredoc-идентификатор двойными кавычками:
|
||
</para>
|
||
|
||
<example>
|
||
<title>Двойные кавычки в heredoc</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo <<<"FOOBAR"
|
||
Привет, мир!
|
||
FOOBAR;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
</sect3>
|
||
|
||
<sect3 xml:id="language.types.string.syntax.nowdoc">
|
||
<title>Nowdoc</title>
|
||
|
||
<para>
|
||
Nowdoc — то же для строк в одинарных кавычках, что и heredoc для строк
|
||
в двойных кавычках. Синтаксис Nowdoc похож на heredoc-синтаксис, но внутри него
|
||
<emphasis>не выполняются интерполяция строк</emphasis>. Конструкция
|
||
легко встраивает PHP-код или другие большие блоки текста без
|
||
предварительного экранирования. В этом он отчасти похож на SGML-конструкцию
|
||
<literal><![CDATA[ ]]></literal>, в том, что он объявляет блок текста,
|
||
который не требует обработки.
|
||
</para>
|
||
|
||
<para>
|
||
Nowdoc задают той же последовательностью символов <literal><<<</literal>,
|
||
что и в heredoc, но следующий за ней идентификатор берут
|
||
в одинарные кавычки, например, <literal><<<'EOT'</literal>.
|
||
Условия, которые распространяются на идентификаторы heredoc-синтаксиса, действительны также
|
||
и для синтаксиса nowdoc, а больше остальных те, что относятся к закрывающему идентификатору.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Пример nowdoc-синтаксиса</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo <<<'EOD'
|
||
Пример текста,
|
||
занимающего несколько строк,
|
||
написанного синтаксисом nowdoc. Обратные слеши выводятся без обработки,
|
||
например, \\ и \'.
|
||
EOD;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Пример текста,
|
||
занимающего несколько строк,
|
||
написанного синтаксисом nowdoc. Обратные слеши выводятся без обработки,
|
||
например, \\ и \'.
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Nowdoc с переменными в строках с двойными кавычками</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
/* Усложнённый пример с переменными. */
|
||
class foo
|
||
{
|
||
public $foo;
|
||
public $bar;
|
||
|
||
function __construct()
|
||
{
|
||
$this->foo = 'Foo';
|
||
$this->bar = array('Bar1', 'Bar2', 'Bar3');
|
||
}
|
||
}
|
||
|
||
$foo = new foo();
|
||
$name = 'Имярек';
|
||
|
||
echo <<<'EOT'
|
||
Меня зовут "$name". Я печатаю $foo->foo.
|
||
Теперь я печатаю {$foo->bar[1]}.
|
||
Это не должно вывести заглавную 'A': \x41
|
||
EOT;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Меня зовут "$name". Я печатаю $foo->foo.
|
||
Теперь я печатаю {$foo->bar[1]}.
|
||
Это не должно вывести заглавную 'A': \x41]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Пример со статичными данными</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class foo
|
||
{
|
||
public $bar = <<<'EOT'
|
||
bar
|
||
EOT;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
</sect3>
|
||
|
||
<sect3 xml:id="language.types.string.parsing">
|
||
<title>Интерполяция строк</title>
|
||
|
||
<simpara>
|
||
PHP умеет подставлять внутри строк значения вместо <link linkend="language.variables">переменных</link>,
|
||
если строку (<type>string</type>) указали в двойных кавычках или heredoc-синтаксисом.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В PHP предусмотрели два вида синтаксиса для указания переменных в строках:
|
||
<link linkend="language.types.string.parsing.basic">базовый</link>
|
||
и <link linkend="language.types.string.parsing.advanced">продвинутый</link>.
|
||
Базовым синтаксисом пользуются чаще, им легко
|
||
встраивать переменную, значение массива (<type>array</type>)
|
||
или свойство объекта (<type>object</type>) с минимумом усилий.
|
||
</simpara>
|
||
|
||
<sect4 xml:id="language.types.string.parsing.basic">
|
||
<title>Базовый синтаксис</title>
|
||
<simpara>
|
||
PHP интерпретирует как переменную и подставит вместо переменной значение этой переменной,
|
||
если встретит в строке знак доллара <literal>$</literal>,
|
||
за которым идут символы, из которых PHP разрешает составлять название переменной.
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$juice = "яблочного";
|
||
|
||
echo "Он выпил немного $juice сока." . PHP_EOL;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Он выпил немного яблочного сока.
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
|
||
<simpara>
|
||
Формально структура базового синтаксиса подстановки переменных
|
||
выглядит вот так:
|
||
</simpara>
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
строковая переменная::
|
||
имя-переменной (смещение-или-свойство)?
|
||
| ${ выражение }
|
||
|
||
смещение-или-свойство::
|
||
смещение в строке
|
||
| свойство-в-строке
|
||
|
||
смещение-в-строке::
|
||
[ имя ]
|
||
| [ имя-переменной ]
|
||
| [ целочисленный-литерал ]
|
||
|
||
свойство-в-строке::
|
||
-> имя
|
||
|
||
имя-переменной::
|
||
$ имя
|
||
|
||
имя::
|
||
[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*
|
||
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<warning>
|
||
<para>
|
||
Синтаксис <literal>${ выражение }</literal> устарел
|
||
с PHP 8.2.0, поскольку интерпретируется
|
||
как <link linkend="language.variables.variable">переменные переменных</link>:
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
const foo = 'bar';
|
||
$foo = 'foo';
|
||
$bar = 'bar';
|
||
var_dump("${foo}");
|
||
var_dump("${(foo)}");
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs.82;
|
||
<screen>
|
||
<![CDATA[
|
||
Deprecated: Using ${var} in strings is deprecated, use {$var} instead in file on line 6
|
||
|
||
Deprecated: Using ${expr} (variable variables) in strings is deprecated, use {${expr}} instead in file on line 9
|
||
string(3) "foo"
|
||
string(3) "bar"
|
||
]]>
|
||
</screen>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
string(3) "foo"
|
||
string(3) "bar"
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
Вместо этого пользуются
|
||
<link linkend="language.types.string.parsing.advanced">продвинутым</link>
|
||
синтаксисом интерполяции строк.
|
||
</para>
|
||
</warning>
|
||
|
||
<note>
|
||
<simpara>
|
||
Знак доллара остается в строке как сам знак доллара,
|
||
если невозможно сформировать допустимое имя:
|
||
</simpara>
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
echo "Строка не содержит переменных $ для интерполяции\n";
|
||
echo "Строка не содержит переменных $\n для интерполяции\n";
|
||
echo "Строка не содержит переменных $2 для интерполяции\n";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Строка не содержит переменных $ для интерполяции
|
||
Строка не содержит переменных $
|
||
для интерполяции
|
||
Строка не содержит переменных $2 для интерполяции
|
||
]]>
|
||
</screen>
|
||
</informalexample>
|
||
</note>
|
||
|
||
<example>
|
||
<title>Пример интерполяции значений первого уровня массива или свойства объекта</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
$juices = array("яблочного", "апельсинового", "string_key" => "фиолетового");
|
||
|
||
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.";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Он выпил немного яблочного сока.
|
||
Он выпил немного апельсинового сока.
|
||
Он выпил немного фиолетового сока.
|
||
Значение свойства объекта: string.
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<note>
|
||
<simpara>
|
||
Ключ массива указывают без кавычек, поэтому невозможно
|
||
ссылаться на константу как на ключ в базовом синтаксисе. Вместо этого пользуются
|
||
<link linkend="language.types.string.parsing.advanced">продвинутым</link>
|
||
синтаксисом.
|
||
</simpara>
|
||
</note>
|
||
|
||
<simpara>
|
||
В PHP 7.1.0 добавили поддержку <emphasis>отрицательных</emphasis>
|
||
числовых индексов.
|
||
</simpara>
|
||
|
||
<example><title>Отрицательные числовые индексы</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$string = 'string';
|
||
echo "Символ с индексом -2 равен $string[-2].", PHP_EOL;
|
||
$string[-3] = 'o';
|
||
echo "Изменение символа на позиции -3 на 'o' даёт следующую строку: $string.", PHP_EOL;
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
Символ с индексом -2 равен n.
|
||
Изменение символа на позиции -3 на «o» даёт следующую строку: strong
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<simpara>
|
||
Для выражений, которые сложнее этих, лучше пользоваться
|
||
<link linkend="language.types.string.parsing.advanced">продвинутым</link>
|
||
синтаксисом.
|
||
</simpara>
|
||
</sect4>
|
||
|
||
<sect4 xml:id="language.types.string.parsing.advanced">
|
||
<title>Продвинутый, или фигурный, синтаксис</title>
|
||
|
||
<simpara>
|
||
Продвинутый синтаксис разрешает интерполировать
|
||
<emphasis>переменные</emphasis> с произвольными методами доступа.
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В строках продвинутым синтаксисом указывают скалярные переменные, элементы массива,
|
||
статические и динамические свойства объекта со строковым представлением.
|
||
Выражение записывается как и вне строки, а затем оборачивается
|
||
в фигурные скобки <literal>{</literal> и <literal>}</literal>.
|
||
Поскольку знак <literal>{</literal> невозможно экранировать, продвинутый синтаксис
|
||
распознаётся только тогда, когда знак <literal>$</literal> идёт непосредственно за знаком <literal>{</literal>.
|
||
Знак доллара экранируют синтаксисом <literal>{\$</literal>, чтобы получить литерал <literal>{$</literal>.
|
||
Поясняющие примеры:
|
||
</simpara>
|
||
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
const DATA_KEY = 'const-key';
|
||
$great = 'здорово';
|
||
|
||
$arr = [
|
||
'1',
|
||
'2',
|
||
'3',
|
||
[41, 42, 43],
|
||
'key' => 'Индексное значение',
|
||
'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";
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<note>
|
||
<simpara>
|
||
В строках с продвинутым синтаксисом возможно записывать
|
||
<link linkend="language.variables.variable">переменные переменных</link>,
|
||
поскольку продвинутый синтаксис разрешает произвольные выражения.
|
||
</simpara>
|
||
</note>
|
||
</sect4>
|
||
</sect3>
|
||
|
||
<sect3 xml:id="language.types.string.substr">
|
||
<title>Доступ к символам и изменение символов в строке</title>
|
||
|
||
<para>
|
||
Символы внутри строк индексируются с начала строки, индексы начинаются с 0.
|
||
Смещение символа, который требуется прочитать или изменить внутри строки,
|
||
указывают после строки в квадратных скобках массива (<type>array</type>),
|
||
например <varname>$str[42]</varname>.
|
||
Для этого о строке думают как о массиве символов.
|
||
Больше одного символа получают и заменяют
|
||
функциями <function>substr</function> и <function>substr_replace</function>.
|
||
</para>
|
||
|
||
<note>
|
||
<simpara>
|
||
Начиная с PHP 7.1.0 поддерживаются отрицательные значения смещения.
|
||
Они задают смещение с конца строки. Раньше отрицательные смещение вызывали
|
||
ошибку уровня <constant>E_NOTICE</constant> при чтении (возвращая пустую строку)
|
||
или <constant>E_WARNING</constant> при записи (оставляя строку без изменений).
|
||
</simpara>
|
||
</note>
|
||
|
||
<note>
|
||
<simpara>
|
||
До PHP 8.0.0 доступ к символам в строках (<type>string</type>) получали,
|
||
указывая фигурные скобки, например <varname>$str{42}</varname>.
|
||
Синтаксис фигурных скобок устарел с PHP 7.4.0 и не поддерживается с PHP 8.0.0.
|
||
</simpara>
|
||
</note>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Попытка записи в смещение за границами строки дополнит строку
|
||
пробелами до этого смещения. Нецелочисленные типы преобразуются в целочисленные.
|
||
Неверный тип смещения выдаст ошибку уровня <constant>E_WARNING</constant>.
|
||
При добавлении в смещение строки новых символов присвоится только первый символ (байт).
|
||
Начиная с PHP 7.1.0 присваивание пустой строки вызовет фатальную ошибку. Раньше
|
||
присваивался нулевой байт (NULL).
|
||
</simpara>
|
||
</warning>
|
||
|
||
<warning>
|
||
<simpara>
|
||
Внутренне PHP представляет строки массивами байтов. Поэтому
|
||
доступ или изменение строки по смещению небезопасны для многобайтовых данных
|
||
и выполняются только со строками в однобайтовых кодировках,
|
||
например ISO-8859-1.
|
||
</simpara>
|
||
</warning>
|
||
|
||
<note>
|
||
<simpara>
|
||
Начиная с PHP 7.1.0 попытка указать оператор пустого индекса
|
||
на пустой строке выдаст фатальную ошибку.
|
||
Раньше пустая строка преобразовывалась в массив без предупреждения.
|
||
</simpara>
|
||
</note>
|
||
|
||
<example>
|
||
<title>Примеры строк</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
// Получим первый символ строки
|
||
$str = 'This is a test.';
|
||
$first = $str[0];
|
||
|
||
// Получим третий символ строки
|
||
$third = $str[2];
|
||
|
||
// Получим последний символ строки
|
||
$str = 'This is still a test.';
|
||
$last = $str[strlen($str)-1];
|
||
|
||
// Изменим последний символ строки
|
||
$str = 'Look at the sea';
|
||
$str[strlen($str)-1] = 'e';
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<para>
|
||
Смещение в строке задают либо целым числом, либо целочисленной строкой,
|
||
иначе PHP выдаст предупреждение.
|
||
</para>
|
||
|
||
<example>
|
||
<!-- TODO Update for PHP 8.0 -->
|
||
<title>Пример недопустимого смещения строки</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$str = 'abc';
|
||
|
||
var_dump($str['1']);
|
||
var_dump(isset($str['1']));
|
||
|
||
var_dump($str['1.0']);
|
||
var_dump(isset($str['1.0']));
|
||
|
||
var_dump($str['x']);
|
||
var_dump(isset($str['x']));
|
||
|
||
var_dump($str['1x']);
|
||
var_dump(isset($str['1x']));
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
string(1) "b"
|
||
bool(true)
|
||
|
||
Warning: Illegal string offset '1.0' in /tmp/t.php on line 7
|
||
string(1) "b"
|
||
bool(false)
|
||
|
||
Warning: Illegal string offset 'x' in /tmp/t.php on line 9
|
||
string(1) "a"
|
||
bool(false)
|
||
string(1) "b"
|
||
bool(false)
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
|
||
<note>
|
||
<para>
|
||
Доступ к переменным других типов, кроме массивов
|
||
и объектов, которые реализуют соответствующие интерфейсы, через операторы <literal>[]</literal>
|
||
или <literal>{}</literal> без предупреждения возвращает &null;.
|
||
</para>
|
||
</note>
|
||
|
||
<note>
|
||
<para>
|
||
Доступ к символам в строковых литералах получают
|
||
через операторы <literal>[]</literal> или <literal>{}</literal>.
|
||
</para>
|
||
</note>
|
||
|
||
<note>
|
||
<para>
|
||
Доступ к символам в строковых литералах
|
||
через оператор <literal>{}</literal> объявили устаревшим в PHP 7.4
|
||
и удалили в PHP 8.0.
|
||
</para>
|
||
</note>
|
||
</sect3>
|
||
</sect2><!-- end syntax -->
|
||
|
||
<sect2 xml:id="language.types.string.useful-funcs">
|
||
<title>Полезные функции и операторы</title>
|
||
|
||
<para>
|
||
Строки объединяют оператором «.» — точки.
|
||
Обратите внимание, оператор сложения «+» здесь <emphasis>не работает</emphasis>.
|
||
Подробнее об этом рассказано в разделе
|
||
«<link linkend="language.operators.string">Строковые операторы</link>».
|
||
</para>
|
||
|
||
<para>
|
||
В языке предусмотрели ряд полезных функций для манипулирования строками.
|
||
</para>
|
||
|
||
<simpara>
|
||
Общие функции описывает раздел
|
||
«<link linkend="ref.strings">Функции для работы со строками</link>», а для расширенного поиска
|
||
и замены — «<link linkend="ref.pcre">Функции Perl-совместимых регулярных выражений</link>».
|
||
</simpara>
|
||
|
||
<simpara>
|
||
В PHP также предусмотрели <link linkend="ref.url">функции для работы с URL-адресами</link>
|
||
и функции шифрования или дешифрования строк (<link linkend="ref.sodium">Sodium</link> и <link linkend="ref.hash">Hash</link>).
|
||
</simpara>
|
||
|
||
<simpara>
|
||
Наконец, смотрите также
|
||
<link linkend="ref.ctype">функции символьных типов</link>.
|
||
</simpara>
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.types.string.casting">
|
||
<title>Преобразование в строку</title>
|
||
|
||
<para>
|
||
Значение преобразовывают в строку приведением
|
||
через оператор <literal>(string)</literal> или функцией <function>strval</function>.
|
||
В выражениях, в которых требуется строка, преобразование выполняется автоматически.
|
||
Это выполняется во время вывода через языковые конструкции <function>echo</function>
|
||
или <function>print</function>, либо когда значение переменной сравнивается
|
||
со строкой. Разделы руководства
|
||
«<link linkend="language.types">Типы</link>»
|
||
и «<link linkend="language.types.type-juggling">Манипуляции с типами</link>»,
|
||
прояснят сказанное ниже. Смотрите также описание функции <function>settype</function>.
|
||
</para>
|
||
|
||
<para>
|
||
Значение <type>bool</type> &true; преобразовывается в строку
|
||
<literal>«1»</literal>, а логическое значение &false; преобразовывается
|
||
в <literal>«»</literal> (пустую строку). Такое поведение допускает преобразование значения
|
||
в обе стороны — из логического типа в строковый и наоборот.
|
||
</para>
|
||
|
||
<para>
|
||
Целое число (<type>int</type>) или число с плавающей точкой
|
||
(<type>float</type>) преобразовывается в строку, которая будет представлять число в текстовом виде
|
||
(включая экспоненциальную часть для чисел с плавающей точкой).
|
||
Большие числа с плавающей точкой преобразовываются в экспоненциальную запись (<literal>4.1E+6</literal>).
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
Начиная с PHP 8.0.0 в качестве разделителя дробной части в числах
|
||
с плавающей точкой разрешено использовать только точку («<literal>.</literal>»).
|
||
До PHP 8.0.0 символ десятичной точки определялся в настройках языкового стандарта скрипта
|
||
(категория LC_NUMERIC). Смотрите функцию <function>setlocale</function>.
|
||
</para>
|
||
</note>
|
||
|
||
<para>
|
||
Массивы преобразовываются в строку <literal>«Array»</literal>.
|
||
Поэтому конструкции <function>echo</function> или <function>print</function>
|
||
не умеют без помощи функций отображать содержимое массива (<type>array</type>).
|
||
Чтобы просмотреть отдельный элемент, пользуются
|
||
синтаксисом <literal>echo $arr['foo']</literal>. Ниже рассказывается
|
||
об отображении или просмотре всего содержимого.
|
||
</para>
|
||
|
||
<para>
|
||
Для преобразования объекта (<literal>object</literal>) в строку (<type>string</type>)
|
||
определяют магический метод
|
||
<link linkend="language.oop5.magic">__toString</link>.
|
||
</para>
|
||
|
||
<para>
|
||
Ресурс (<type>resource</type>) преобразовывается в строку (<type>string</type>) вида
|
||
<literal>«Resource id #1»</literal>, где <literal>1</literal> —
|
||
это номер ресурса, который PHP назначает ресурсу (<type>resource</type>) во время исполнения кода.
|
||
И хотя она уникальна для текущего запуска скрипта (т. е. веб-запроса или
|
||
CLI-процесса) и не будет использована повторно для этого ресурса,
|
||
не стоит полагаться на эту строку, потому что её могут изменить в будущем.
|
||
Тип ресурса можно получить вызовом функции <function>get_resource_type</function>.
|
||
</para>
|
||
|
||
<para>
|
||
Значение &null; всегда преобразовывается в пустую строку.
|
||
</para>
|
||
|
||
<para>
|
||
Как указано выше, прямое преобразование в строку массивов, объектов
|
||
или ресурсов не даёт полезной информации о значении, кроме типа.
|
||
Более эффективные инструменты вывода значений для отладки этих типов — это функции
|
||
<function>print_r</function> и <function>var_dump</function>.
|
||
</para>
|
||
|
||
<para>
|
||
Бо́льшая часть значений в PHP преобразуема в строку для постоянного
|
||
хранения. Этот метод преобразования называется сериализацией. Сериализуют значения
|
||
функцией <function>serialize</function>.
|
||
</para>
|
||
|
||
</sect2>
|
||
|
||
<sect2 xml:id="language.types.string.details">
|
||
|
||
<title>Подробные сведения о строковом типе</title>
|
||
|
||
<para>
|
||
Строковый тип (<type>string</type>) в PHP реализовали в виде массива
|
||
байтов и целочисленного значения, которое содержит длину буфера. В этой структуре
|
||
нет информации о том, как преобразовывать байты в символы,
|
||
эту задачу решает программист. Нет ограничений на значения, из которых состоит строка,
|
||
например, байт со значением <literal>0</literal> (NUL-байт) разрешается
|
||
где угодно в строке (однако рекомендуют учитывать, что ряд функций,
|
||
которые в этом руководстве назвали «бинарно небезопасными»,
|
||
передают строки библиотекам, которые игнорируют данные после NUL-байта).
|
||
</para>
|
||
<para>
|
||
Такая природа строкового типа объясняет, почему в PHP нет отдельного
|
||
типа «byte» — строки выполняют эту роль. Функции, которые не возвращают текстовых данных, —
|
||
например, произвольный поток данных, считываемый из сетевого сокета, —
|
||
по-прежнему возвращают строки.
|
||
</para>
|
||
<para>
|
||
С учётом того, что PHP не диктует конкретную кодировку
|
||
для строк, может возникнуть вопрос: Как тогда кодируются строковые
|
||
литералы? Например, строка <literal>«á»</literal> эквивалентна
|
||
<literal>«\xE1»</literal> (ISO-8859-1), <literal>«\xC3\xA1»</literal>
|
||
(UTF-8, форма нормализации C), <literal>«\x61\xCC\x81»</literal>
|
||
(UTF-8, форма нормализации D) или другому возможному
|
||
представлению? Ответ такой: строка будет закодирована
|
||
способом, которым она закодирована в файле скрипта. Поэтому, если
|
||
скрипт записан в кодировке ISO-8859-1, то и строка будет закодирована в
|
||
ISO-8859-1 и т. д. Однако это правило не выполняется при включённом
|
||
режиме Zend Multibyte: скрипт записывают в произвольной
|
||
кодировке, объявляя её или полагаясь на автоопределение,
|
||
а затем конвертируют в конкретную внутреннюю кодировку, которая и будет
|
||
использована для строковых литералов.
|
||
Учтите, что на кодировку скрипта (или на внутреннюю кодировку, если
|
||
включён режим Zend Multibyte) накладывается ряд ограничений:
|
||
почти в каждом случае эта кодировка должна быть надмножеством кодировки ASCII,
|
||
например, UTF-8 или ISO-8859-1. Учтите также, что кодировки, зависящие
|
||
от состояния, где одни и те же значения байтов допустимы
|
||
в начальном и не начальном состоянии сдвига, создают риск проблем.
|
||
</para>
|
||
<para>
|
||
Строковые функции, чтобы быть полезными, пробуют предположить кодировку строки.
|
||
Единство в этом вопросе не помешало бы, но PHP-функции работают с текстом по-разному:
|
||
</para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<simpara>
|
||
Одни — предполагают, что строка закодирована в какой-то
|
||
однобайтовой кодировке, но для корректной работы
|
||
им не нужно интерпретировать байты как конкретные символы.
|
||
Сюда попадают функции вроде <function>substr</function>,
|
||
<function>strpos</function>, <function>strlen</function>
|
||
и <function>strcmp</function>. Другой способ мышления об этих функциях —
|
||
представлять, что они оперируют буферами памяти, т. е. работают
|
||
непосредственно с байтами и их смещениями.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Другим — передаётся кодировка строки или они принимают
|
||
значение по умолчанию, если кодировку не передали.
|
||
Это относится к функции <function>htmlentities</function>
|
||
и большей части функций модуля <link linkend="book.mbstring">mbstring</link>.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Третьи — работают с текущими настройками локали (смотрите
|
||
<function>setlocale</function>), но оперируют побайтово.
|
||
</simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara>
|
||
Наконец четвёртые — предполагают, что строка использует
|
||
конкретную кодировку, обычно UTF-8. Сюда попадает бо́льшая часть
|
||
функций из модулей <link linkend="book.intl">intl</link>
|
||
и <link linkend="book.pcre">PCRE</link>
|
||
(для последнего — только при указании модификатора <literal>u</literal>).
|
||
</simpara>
|
||
</listitem>
|
||
</itemizedlist>
|
||
|
||
<para>
|
||
В конечном счёте, программа будет работать с кодировкой Unicode правильно,
|
||
если старательно избегать функций,
|
||
которые не будут работать с Unicode-строками или повредят данные, и вызывать вместо них те,
|
||
которые ведут себя корректно, обычно это функции из модулей <link linkend="book.intl">intl</link>
|
||
и <link linkend="book.mbstring">mbstring</link>.
|
||
Однако работа с функциями, которые умеют обрабатывать Unicode, —
|
||
это только начало. Независимо от того, какие функции предлагает
|
||
язык, рекомендовано знать спецификацию Unicode. Например, программа,
|
||
которая предполагает существование только прописных и строчных букв,
|
||
делает неверное предположение.
|
||
</para>
|
||
</sect2>
|
||
</sect1>
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|