1
0
mirror of https://github.com/php/doc-uk.git synced 2026-03-23 22:52:14 +01:00
Files
archived-doc-uk/language/types/string.xml

1383 lines
46 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0" encoding="utf-8"?>
<!-- EN-Revision: 887c21f977369af0808290874dc2c279ad4d0af2 Maintainer: mproshchuk Status: wip -->
<sect1 xml:id="language.types.string">
<title>Рядок (string)</title>
<para>
Рядок (<type>string</type>) — це набір символів, кожному з яких відповідає
певний байт. Це означає, що PHP підтримує всього 256 різних символів, а отже
не має вбудованої підтримки Unicode. Див.
<link linkend="language.types.string.details">деталі про рядковий тип</link>.
</para>
<note>
<simpara>
В 32-бітних збірках значення типу <type>string</type> може мати розмір до
2ГБ (2147483647 байт).
</simpara>
</note>
<sect2 xml:id="language.types.string.syntax">
<title>Синтаксис</title>
<para>
Записувати символами значення типу <type>string</type> можна чотирма
способами:
</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>
Найпростіший спосіб означити рядок (<type>string</type>) — взяти його в
апострофи (наприклад <literal>'це рядкове значення'</literal>).
</para>
<para>
Щоб вписати в рядок апостроф, цей знак необхідно екранувати
оберненою косою рискою (<literal>\</literal>). Щоб всередині рядкового
значення вписати обернену косу риску, треба продублювати її
(<literal>\\</literal>). Всі наступні символи оберненої косої риски будуть
сприйматись буквально: це означає, що всі інші екрановані послідовності,
наприклад <literal>\r</literal> або <literal>\n</literal> будуть виводитись
буквально, а не як такі, що мають спеціальне значення.
</para>
<note>
<simpara>
На відміну від
<link linkend="language.types.string.syntax.double">лапок</link>
та синтаксису
<link linkend="language.types.string.syntax.heredoc">heredoc</link>,
<link linkend="language.variables">змінні</link> та екрановані
послідовності спеціальних символів <emphasis>не</emphasis> будуть
розкриті в рядках, взятих в апострофи.
</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 a newline
echo 'Це не розкриється: \n a newline';
// Виводить: Змінні $також $не_розкриваються
echo 'Змінні $також $не_розкриваються';
?>
]]>
</programlisting>
</informalexample>
</sect3>
<sect3 xml:id="language.types.string.syntax.double">
<title>Лапки</title>
<para>
Якщо рядок (<type>string</type>) взято в лапки (<literal>"</literal>), то
PHP інтерпретує наступні екрановані послідовності у спеціальні символи:
</para>
<table>
<title>Екрановані символи</title>
<tgroup cols="2">
<thead>
<row>
<entry>Послідовність</entry>
<entry>Значення</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>\n</literal></entry>
<entry>новий рядок (LF (linefeed) або 0x0A (10) в ASCII)</entry>
</row>
<row>
<entry><literal>\r</literal></entry>
<entry>повернення каретки (CR (carriage return) або 0x0D (13) в ASCII)</entry>
</row>
<row>
<entry><literal>\t</literal></entry>
<entry>горизонтальна табуляція (HT (horizontal tab) або 0x09 (9) в ASCII)</entry>
</row>
<row>
<entry><literal>\v</literal></entry>
<entry>вертикальна табуляція (VT (vertical tab) або 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 (form feed) або 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>[0-7]{1,3}</literal> та є вісімковою формою запису
символа (напр. <literal>"\101" === "A"</literal>), що неявно
переповнюється, щоб відповідати одному байту (напр.
<literal>"\400" === "\000"</literal>)
</entry>
</row>
<row>
<entry><literal>\x[0-9A-Fa-f]{1,2}</literal></entry>
<entry>
Шістнадцяткове число: послідовність символів, що відповідає регулярному
виразу <literal>[0-9A-Fa-f]{1,2}</literal> та є шістнадцятковою формою
запису символа (напр. <literal>"\x41" === "A"</literal>)
</entry>
</row>
<row>
<entry><literal>\u{[0-9A-Fa-f]+}</literal></entry>
<entry>
Unicode: послідовність символів, що відповідає регулярному виразу
<literal>[0-9A-Fa-f]+</literal> та є кодовою точкою UTF-8, символ якої
буде вставлено у рядок. Фігурні дужки є обов'язковими у цій
послідовності. Наприклад <literal>"\u{41}" === "A"</literal>
</entry>
</row>
</tbody>
</tgroup>
</table>
<para>
В рядках (<type>string</type>), що взяті в апострофи, екранування інших
символів також призведе до друку оберненої косої риски.
</para>
<para>
Найважливішою особливістю рядків (<type>string</type>) в лапках є
розкривання значень змінних. Детальніше:
<link linkend="language.types.string.parsing">Інтерполяція рядків</link>.
</para>
</sect3>
<sect3 xml:id="language.types.string.syntax.heredoc">
<title>Heredoc</title>
<simpara>
Третій спосіб запису значення типу <type>string</type> — синтаксис heredoc:
<literal>&lt;&lt;&lt;</literal>. Після цього оператора слідують
мітка та символ нового рядка. Далі — власне, текст (<type>string</type>), а
потім та сама мітка з нового рядка. Вона позначає кінець тексту.
</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 <<<МІТКА
а
б
в
\n
МІТКА;
// відступ з 4-х пропусків
echo <<<МІТКА
а
б
в
МІТКА;
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
а
б
в
а
б
в
]]>
</screen>
</example>
<simpara>
Якщо кінцева мітка відступає далі ніж будь-який рядок тексту, то викинеться
<classname>ParseError</classname>:
</simpara>
<example>
<title>Кінцева мітка не має відступати далі ніж будь-який рядок тексту</title>
<programlisting role="php">
<![CDATA[
<?php
echo <<<МІТКА
а
б
в
МІТКА;
]]>
</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>
Для відступу кінцевої мітки можна використовувати табуляцію, однак табуляція
та пропуски <emphasis>не повинні</emphasis> змішуватися у відступах тексту
чи кінцевої мітки. Інакше, буде викинуто <classname>ParseError</classname>.
Це обмеження було введено у зв'язку з тим, що змішування табуляції та
пропусків погіршує розбірливість коду.
</simpara>
<example>
<title>Різні відступи</title>
<programlisting role="php">
<![CDATA[
<?php
// Увесь наступний код не працює.
// різні відступи в тексті (пропуски) та для кінцевої мітки (табуляція)
{
echo <<<МІТКА
а
МІТКА;
}
// змішування пропусків та табуляції в тексті
{
echo <<<МІТКА
а
МІТКА;
}
// змішування пропусків та табуляції для кінцевої мітки
{
echo <<<МІТКА
а
МІТКА;
}
]]>
</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
$значення = [<<<МІТКА
а
б
в
МІТКА, 'г ґ д'];
var_dump($значення);
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
array(2) {
[0]=>
string(14) "а
б
в"
[1]=>
string(8) "г ґ д"
}
]]>
</screen>
</example>
<warning>
<simpara>
Якщо назву мітки знайдено одразу після символу початку рядка, то навіть
якщо це була частина тексту, вона розглядатиметься як кінцева мітка, що
спричинить помилку <classname>ParseError</classname>.
</simpara>
<example>
<title>Кінцева мітка в тексті може викликати ParseError</title>
<programlisting role="php">
<![CDATA[
<?php
$значення = [<<<МІТКА
а
б
МІТКА помічає кінець тексту
МІТКА, 'в г ґ'];
]]>
</programlisting>
&example.outputs.73;
<screen>
<![CDATA[
PHP Parse error: syntax error, unexpected identifier "помічає", expecting "]" in example.php on line 5
]]>
</screen>
</example>
<simpara>
Щоб уникнути цієї проблеми, безпечніше дотримуватися простого правила:
<emphasis>не обирати мітку, яка може з'явитися в тексті</emphasis>.
</simpara>
</warning>
<warning>
<simpara>
До PHP 7.3.0, необхідно слідкувати за тим, щоб рядок з кінцевою міткою не
містив нічого, крім самої мітки та крапки з комою (<literal>;</literal>) за
нею. Це означає, що мітка <emphasis>не може відступати</emphasis> від
початку рядка, а також не може бути жодних пропусків чи табуляції перед чи
після крапки з комою. Також важливо, щоб символом перед кінцевою міткою
був символ нового рядка, визначений локальною операційною системою. Це
<literal>\n</literal> в системах UNIX, включно з macOS. Також цей символ
має бути одразу після крапки з комою.
</simpara>
<simpara>
Якщо це правило порушено і кінцева мітка неправильна — вона не
вважатиметься такою, а PHP продовжить шукати кінцеву мітку. Якщо до кінця
поточного файлу мітку не буде знайдено, то на останньому рядку виникне
синтаксична помилка.
</simpara>
<example>
<title>Недійсна мітка, до версії PHP 7.3.0</title>
<programlisting role="php">
<!-- This is an INVALID example -->
<![CDATA[
<?php
class foo {
public $bar = <<<МІТКА
bar
МІТКА;
}
// Мітка повинна не мати відступів
?>
]]>
</programlisting>
</example>
<example>
<title>Дійсна мітка, навіть до версії PHP 7.3.0</title>
<programlisting role="php">
<!-- This is a VALID example -->
<![CDATA[
<?php
class foo {
public $bar = <<<МІТКА
bar
МІТКА;
}
?>
]]>
</programlisting>
</example>
<para>
Дані рядкового типу в синтаксисі Heredoc, які містять змінні, не можна
використовувати для ініціалізації властивостей класу.
</para>
</warning>
<para>
Текст Heredoc має ті ж особливості, що і рядок (<type>string</type>) в
лапках, просто без лапок. Це означає, що лапки в Heredoc не потрібно
екранувати, а перелічені вище екрановані послідовності досі можна
використовувати. Змінні так само розкриваються, а складні змінні записуються
тим же способом, що і в рядках (<type>string</type>).
</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 — рядків в
лапках, тобто працює схожим способом до heredoc, але <emphasis>без
інтерполяції тексту</emphasis> всередині. Така конструкція прекрасно
підходить для вставлення PHP-коду або великих частин тексту без необхідності
їхнього екранування. Цей синтаксис має деякі спільні риси з конструкцією
SGML <literal>&lt;![CDATA[ ]]&gt;</literal>, оскільки він оголошує блок
тексту, який не підлягає аналізу.
</para>
<para>
Nowdoc починається з тої ж послідовності <literal>&lt;&lt;&lt;</literal>, що
й heredocs, але назва мітки, що йде далі, береться в апострофи, напр.
<literal>&lt;&lt;&lt;'EOT'</literal>. Усі правила щодо міток heredoc
застосовуються також до міток nowdoc, особливо ті, що стосуються кінцевої
мітки.
</para>
<example>
<title>Приклад тексту nowdoc</title>
<programlisting role="php">
<![CDATA[
<?php
echo <<<'МІТКА'
Приклад тексту з кількома рядками
з використанням синтаксису nowdoc.
Зворотні косі риски завжди спиймаються буквально, напр. \\ і \'.
МІТКА;
]]>
</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>
Якщо рядок (<type>string</type>) записано в лапках або в heredoc, то
в нього можна вставляти <link linkend="language.variables">змінні</link>.
</simpara>
<simpara>
Є два способи запису:
<link linkend="language.types.string.parsing.basic">основний</link> та
<link linkend="language.types.string.parsing.advanced">розширений</link>.
Основний синтаксис є найпоширенішим і найзручнішим. Він надає можливість
вбудувати змінну, значення масиву (<type>array</type>), або властивість
об'єкта (<type>object</type>) в рядок (<type>string</type>) з невеликими
зусиллями.
</simpara>
<sect4 xml:id="language.types.string.parsing.basic">
<title>Основний синтаксис</title>
<simpara>
Якщо трапляється знак долара (<literal>$</literal>), а після — символи, що
є допустимими у назві змінної, то така послідовність вважається, власне,
змінною, а в текст замість неї підставляється її рядкове значення.
</simpara>
<informalexample>
<programlisting role="php">
<![CDATA[
<?php
$фрукт = "персик";
echo "Він з'їв $фрукт." . PHP_EOL;
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Він з'їв персик.
]]>
</screen>
</informalexample>
<simpara>
Формально, структура основного синтаксису підставлення змінних є такою:
</simpara>
<informalexample>
<programlisting>
<![CDATA[
рядкова-змінна::
назва-змінної (зміщення-або-властивість)?
| ${ вираз }
зміщення-або-властивість::
зміщення-в-рядку
| властивість-в-рядку
зміщення-в-рядкуg::
[ назва ]
| [ назва-змінної ]
| [ цифровий-літерал ]
властивість-в-рядку::
-> назва
назва-змінної::
$ назва
назва::
[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 = "рядок";
}
$o = new A();
echo "Значення об'єкту: $o->s.";
?>
]]>
</programlisting>
&example.outputs;
<screen>
<![CDATA[
Він випив яблучний сік.
Він випив апельсиновий сік.
Він випив фіолетовий сік.
Значення об'єкту: рядок.
]]>
</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>
Будь-яка скалярна змінна, елемент масиву або властивість об'єкту
(<modifier>static</modifier> чи ні) з рядковим (<type>string</type>)
представленням можна вставити в рядок за допомогою цього синтаксису. Вираз
записується так, як він виглядає поза рядком (<type>string</type>) та
береться в фігурні дужки (<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 = 'fantastic';
$arr = [
'1',
'2',
'3',
[41, 42, 43],
'key' => 'Indexed value',
'const-key' => 'Key with minus sign',
'foo' => ['foo1', 'foo2', 'foo3']
];
// Won't work, outputs: This is { fantastic}
echo "This is { $great}";
// Works, outputs: This is fantastic
echo "This is {$great}";
class Square {
public $width;
public function __construct(int $width) { $this->width = $width; }
}
$square = new Square(5);
// Works
echo "This square is {$square->width}00 centimeters wide.";
// Works, quoted keys only work using the curly brace syntax
echo "This works: {$arr['key']}";
// Works
echo "This works: {$arr[3][2]}";
echo "This works: {$arr[DATA_KEY]}";
// When using multidimensional arrays, always use braces around arrays
// when inside of strings
echo "This works: {$arr['foo'][2]}";
echo "This works: {$obj->values[3]->name}";
echo "This works: {$obj->$staticProp}";
// Won't work, outputs: C:\folder\{fantastic}.txt
echo "C:\folder\{$great}.txt";
// Works, outputs: C:\folder\fantastic.txt
echo "C:\\folder\\{$great}.txt";
?>
]]>
</programlisting>
</informalexample>
<note>
<simpara>
As this syntax allows arbitrary expressions it is possible to use
<link linkend="language.variables.variable">variable variables</link>
within the advanced syntax.
</simpara>
</note>
</sect4>
</sect3>
<sect3 xml:id="language.types.string.substr">
<title>String access and modification by character</title>
<para>
Characters within <type>string</type>s may be accessed and modified by
specifying the zero-based offset of the desired character after the
<type>string</type> using square <type>array</type> brackets, as in
<varname>$str[42]</varname>. Think of a <type>string</type> as an
<type>array</type> of characters for this purpose. The functions
<function>substr</function> and <function>substr_replace</function>
can be used when you want to extract or replace more than 1 character.
</para>
<note>
<simpara>
As of PHP 7.1.0, negative string offsets are also supported. These specify
the offset from the end of the string.
Formerly, negative offsets emitted <constant>E_NOTICE</constant> for reading
(yielding an empty string) and <constant>E_WARNING</constant> for writing
(leaving the string untouched).
</simpara>
</note>
<note>
<simpara>
Prior to PHP 8.0.0, <type>string</type>s could also be accessed using braces, as in
<varname>$str{42}</varname>, for the same purpose.
This curly brace syntax was deprecated as of PHP 7.4.0 and no longer supported as of PHP 8.0.0.
</simpara>
</note>
<warning>
<simpara>
Writing to an out of range offset pads the string with spaces.
Non-integer types are converted to integer.
Illegal offset type emits <constant>E_WARNING</constant>.
Only the first character of an assigned string is used.
As of PHP 7.1.0, assigning an empty string throws a fatal error. Formerly,
it assigned a NULL byte.
</simpara>
</warning>
<warning>
<simpara>
Internally, PHP strings are byte arrays. As a result, accessing or
modifying a string using array brackets is not multi-byte safe, and
should only be done with strings that are in a single-byte encoding such
as ISO-8859-1.
</simpara>
</warning>
<note>
<simpara>
As of PHP 7.1.0, applying the empty index operator on an empty string throws a fatal
error. Formerly, the empty string was silently converted to an array.
</simpara>
</note>
<example>
<title>Some string examples</title>
<programlisting role="php">
<![CDATA[
<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str[0];
// Get the third character of a string
$third = $str[2];
// Get the last character of a string.
$str = 'This is still a test.';
$last = $str[strlen($str)-1];
// Modify the last character of a string
$str = 'Look at the sea';
$str[strlen($str)-1] = 'e';
?>
]]>
</programlisting>
</example>
<para>
String offsets have to either be integers or integer-like strings,
otherwise a warning will be thrown.
</para>
<example>
<!-- TODO Update for PHP 8.0 -->
<title>Example of Illegal String Offsets</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>
Accessing variables of other types (not including arrays or objects
implementing the appropriate interfaces) using <literal>[]</literal> or
<literal>{}</literal> silently returns &null;.
</para>
</note>
<note>
<para>
Characters within string literals can be accessed
using <literal>[]</literal> or <literal>{}</literal>.
</para>
</note>
<note>
<para>
Accessing characters within string literals using the
<literal>{}</literal> syntax has been deprecated in PHP 7.4.
This has been removed in PHP 8.0.
</para>
</note>
</sect3>
</sect2><!-- end syntax -->
<sect2 xml:id="language.types.string.useful-funcs">
<title>Useful functions and operators</title>
<para>
<type>String</type>s may be concatenated using the '.' (dot) operator. Note
that the '+' (addition) operator will <emphasis>not</emphasis> work for this.
See <link linkend="language.operators.string">String operators</link> for
more information.
</para>
<para>
There are a number of useful functions for <type>string</type> manipulation.
</para>
<simpara>
See the <link linkend="ref.strings">string functions section</link> for
general functions, and the <link linkend="ref.pcre">Perl-compatible regular
expression functions</link> for advanced find &amp; replace functionality.
</simpara>
<simpara>
There are also <link linkend="ref.url">functions for URL strings</link>, and
functions to encrypt/decrypt strings
(<link linkend="ref.sodium">Sodium</link> and
<link linkend="ref.hash">Hash</link>).
</simpara>
<simpara>
Finally, see also the <link linkend="ref.ctype">character type
functions</link>.
</simpara>
</sect2>
<sect2 xml:id="language.types.string.casting">
<title>Converting to string</title>
<para>
A value can be converted to a <type>string</type> using the
<literal>(string)</literal> cast or the <function>strval</function> function.
<type>String</type> conversion is automatically done in the scope of an
expression where a <type>string</type> is needed. This happens when using the
<function>echo</function> or <function>print</function> functions, or when a
variable is compared to a <type>string</type>. The sections on
<link linkend="language.types">Types</link> and
<link linkend="language.types.type-juggling">Type Juggling</link> will make
the following clearer. See also the <function>settype</function> function.
</para>
<para>
A <type>bool</type> &true; value is converted to the <type>string</type>
<literal>"1"</literal>. <type>bool</type> &false; is converted to
<literal>""</literal> (the empty string). This allows conversion back and
forth between <type>bool</type> and <type>string</type> values.
</para>
<para>
An <type>int</type> or <type>float</type> is converted to a
<type>string</type> representing the number textually (including the
exponent part for <type>float</type>s). Floating point numbers can be
converted using exponential notation (<literal>4.1E+6</literal>).
</para>
<note>
<para>
As of PHP 8.0.0, the decimal point character is always
a period ("<literal>.</literal>"). Prior to PHP 8.0.0,
the decimal point character is defined in the script's locale (category
LC_NUMERIC). See the <function>setlocale</function> function.
</para>
</note>
<para>
<type>Array</type>s are always converted to the <type>string</type>
<literal>"Array"</literal>; because of this, <function>echo</function> and
<function>print</function> can not by themselves show the contents of an
<type>array</type>. To view a single element, use a construction such as
<literal>echo $arr['foo']</literal>. See below for tips on viewing the entire
contents.
</para>
<para>
In order to convert <type>object</type>s to <type>string</type>, the magic
method <link linkend="language.oop5.magic">__toString</link> must be used.
</para>
<para>
<type>Resource</type>s are always converted to <type>string</type>s with the
structure <literal>"Resource id #1"</literal>, where <literal>1</literal>
is the resource number assigned to the <type>resource</type> by PHP at
runtime. While the exact structure of this string should not be relied on
and is subject to change, it will always be unique for a given resource
within the lifetime of a script being executed (ie a Web request or CLI
process) and won't be reused. To get a <type>resource</type>'s type, use
the <function>get_resource_type</function> function.
</para>
<para>
&null; is always converted to an empty string.
</para>
<para>
As stated above, directly converting an <type>array</type>,
<type>object</type>, or <type>resource</type> to a <type>string</type> does
not provide any useful information about the value beyond its type. See the
functions <function>print_r</function> and <function>var_dump</function> for
more effective means of inspecting the contents of these types.
</para>
<para>
Most PHP values can also be converted to <type>string</type>s for permanent
storage. This method is called serialization, and is performed by the
<function>serialize</function> function.
</para>
</sect2>
<sect2 xml:id="language.types.string.details">
<title>Details of the String Type</title>
<para>
The <type>string</type> in PHP is implemented as an array of bytes and an
integer indicating the length of the buffer. It has no information about how
those bytes translate to characters, leaving that task to the programmer.
There are no limitations on the values the string can be composed of; in
particular, bytes with value <literal>0</literal> (“NUL bytes”) are allowed
anywhere in the string (however, a few functions, said in this manual not to
be “binary safe”, may hand off the strings to libraries that ignore data
after a NUL byte.)
</para>
<para>
This nature of the string type explains why there is no separate “byte” type
in PHP strings take this role. Functions that return no textual data for
instance, arbitrary data read from a network socket will still return
strings.
</para>
<para>
Given that PHP does not dictate a specific encoding for strings, one might
wonder how string literals are encoded. For instance, is the string
<literal>"á"</literal> equivalent to <literal>"\xE1"</literal> (ISO-8859-1),
<literal>"\xC3\xA1"</literal> (UTF-8, C form),
<literal>"\x61\xCC\x81"</literal> (UTF-8, D form) or any other possible
representation? The answer is that string will be encoded in whatever fashion
it is encoded in the script file. Thus, if the script is written in
ISO-8859-1, the string will be encoded in ISO-8859-1 and so on. However,
this does not apply if Zend Multibyte is enabled; in that case, the script
may be written in an arbitrary encoding (which is explicitly declared or is
detected) and then converted to a certain internal encoding, which is then
the encoding that will be used for the string literals.
Note that there are some constraints on the encoding of the script (or on the
internal encoding, should Zend Multibyte be enabled) this almost always
means that this encoding should be a compatible superset of ASCII, such as
UTF-8 or ISO-8859-1. Note, however, that state-dependent encodings where
the same byte values can be used in initial and non-initial shift states
may be problematic.
</para>
<para>
Of course, in order to be useful, functions that operate on text may have to
make some assumptions about how the string is encoded. Unfortunately, there
is much variation on this matter throughout PHPs functions:
</para>
<itemizedlist>
<listitem>
<simpara>
Some functions assume that the string is encoded in some (any) single-byte
encoding, but they do not need to interpret those bytes as specific
characters. This is case of, for instance, <function>substr</function>,
<function>strpos</function>, <function>strlen</function> or
<function>strcmp</function>. Another way to think of these functions is
that operate on memory buffers, i.e., they work with bytes and byte
offsets.
</simpara>
</listitem>
<listitem>
<simpara>
Other functions are passed the encoding of the string, possibly they also
assume a default if no such information is given. This is the case of
<function>htmlentities</function> and the majority of the
functions in the <link linkend="book.mbstring">mbstring</link> extension.
</simpara>
</listitem>
<listitem>
<simpara>
Others use the current locale (see <function>setlocale</function>), but
operate byte-by-byte.
</simpara>
</listitem>
<listitem>
<simpara>
Finally, they may just assume the string is using a specific encoding,
usually UTF-8. This is the case of most functions in the
<link linkend="book.intl">intl</link> extension and in the
<link linkend="book.pcre">PCRE</link> extension
(in the last case, only when the <literal>u</literal> modifier is used).
</simpara>
</listitem>
</itemizedlist>
<para>
Ultimately, this means writing correct programs using Unicode depends on
carefully avoiding functions that will not work and that most likely will
corrupt the data and using instead the functions that do behave correctly,
generally from the <link linkend="book.intl">intl</link> and
<link linkend="book.mbstring">mbstring</link> extensions.
However, using functions that can handle Unicode encodings is just the
beginning. No matter the functions the language provides, it is essential to
know the Unicode specification. For instance, a program that assumes there is
only uppercase and lowercase is making a wrong assumption.
</para>
</sect2>
</sect1><!-- end string -->
<!-- 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
-->