PHP 8.4.2 Released!

Рядок (string)

Рядок (string) — це набір символів, кожному з яких відповідає певний байт. Це означає, що PHP підтримує всього 256 різних символів, а отже не має вбудованої підтримки Unicode. Див. деталі про рядковий тип.

Зауваження: В 32-бітних збірках значення типу string може мати розмір до 2ГБ (2147483647 байт).

Синтаксис

Записувати символами значення типу string можна чотирма способами:

Апострофи

Найпростіший спосіб означити рядок (string) — взяти його в апострофи (наприклад 'це рядкове значення').

Щоб вписати в рядок апостроф, цей знак необхідно екранувати оберненою косою рискою (\). Щоб всередині рядкового значення вписати обернену косу риску, треба продублювати її (\\). Всі наступні символи оберненої косої риски будуть сприйматись буквально: це означає, що всі інші екрановані послідовності, наприклад \r або \n будуть виводитись буквально, а не як такі, що мають спеціальне значення.

Зауваження: На відміну від лапок та синтаксису heredoc, змінні та екрановані послідовності спеціальних символів не будуть розкриті в рядках, взятих в апострофи.

<?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 'Змінні $також $не_розкриваються';
?>

Лапки

Якщо рядок (string) взято в лапки ("), то PHP інтерпретує наступні екрановані послідовності у спеціальні символи:

Екрановані символи
Послідовність Значення
\n новий рядок (LF (linefeed) або 0x0A (10) в ASCII)
\r повернення каретки (CR (carriage return) або 0x0D (13) в ASCII)
\t горизонтальна табуляція (HT (horizontal tab) або 0x09 (9) в ASCII)
\v вертикальна табуляція (VT (vertical tab) або 0x0B (11) в ASCII)
\e escape-символ (ESC або 0x1B (27) в ASCII)
\f розрив сторінки (FF (form feed) або 0x0C (12) в ASCII)
\\ обернена коса риска
\$ знак долара
\" лапка
\[0-7]{1,3} Вісімкове число: послідовність символів, що відповідає регулярному виразу [0-7]{1,3} та є вісімковою формою запису символа (напр. "\101" === "A"), що неявно переповнюється, щоб відповідати одному байту (напр. "\400" === "\000")
\x[0-9A-Fa-f]{1,2} Шістнадцяткове число: послідовність символів, що відповідає регулярному виразу [0-9A-Fa-f]{1,2} та є шістнадцятковою формою запису символа (напр. "\x41" === "A")
\u{[0-9A-Fa-f]+} Unicode: послідовність символів, що відповідає регулярному виразу [0-9A-Fa-f]+ та є кодовою точкою UTF-8, символ якої буде вставлено у рядок. Фігурні дужки є обов'язковими у цій послідовності. Наприклад "\u{41}" === "A"

В рядках (string), що взяті в апострофи, екранування інших символів також призведе до друку оберненої косої риски.

Найважливішою особливістю рядків (string) в лапках є розкривання значень змінних. Детальніше: Інтерполяція рядків.

Heredoc

Третій спосіб запису значення типу string — синтаксис heredoc: <<<. Після цього оператора слідують мітка та символ нового рядка. Далі — власне, текст (string), а потім та сама мітка з нового рядка. Вона позначає кінець тексту.

В кінці перед міткою можуть бути пропуски або символи табуляції. Тоді такі ж відступи будуть видалені з початку усіх рядків тексту. До PHP 7.3.0, мітка в кінці повинна бути одразу після символа нового рядка.

Також мітка має відповідати правилам називання міткок в PHP: містити тільки букви, цифри, підкреслення та починатися з букви або підкреслення.

Приклад #1 Простий приклад Heredoc, починаючи з PHP 7.3.0

<?php
// без відступів
echo <<<МІТКА
а
б
в
\n
МІТКА;

// відступ з 4-х пропусків
echo <<<МІТКА
а
б
в
МІТКА;

В PHP 7.3 поданий вище приклад виведе:

      а
     б
    в

  а
 б
в

Якщо кінцева мітка відступає далі ніж будь-який рядок тексту, то викинеться ParseError:

Приклад #2 Кінцева мітка не має відступати далі ніж будь-який рядок тексту

<?php
echo <<<МІТКА
а
б
в
МІТКА;

В PHP 7.3 поданий вище приклад виведе:

PHP Parse error:  Invalid body indentation level (expecting an indentation level of at least 3) in example.php on line 4

Для відступу кінцевої мітки можна використовувати табуляцію, однак табуляція та пропуски не повинні змішуватися у відступах тексту чи кінцевої мітки. Інакше, буде викинуто ParseError. Це обмеження було введено у зв'язку з тим, що змішування табуляції та пропусків погіршує розбірливість коду.

Приклад #3 Різні відступи

<?php
// Увесь наступний код не працює.

// різні відступи в тексті (пропуски) та для кінцевої мітки (табуляція)
{
echo <<<МІТКА
а
МІТКА;
}

// змішування пропусків та табуляції в тексті
{
echo <<<МІТКА
а
МІТКА;
}

// змішування пропусків та табуляції для кінцевої мітки
{
echo <<<МІТКА
а
МІТКА;
}

В PHP 7.3 поданий вище приклад виведе:

PHP Parse error:  Invalid indentation - tabs and spaces cannot be mixed in example.php line 8

Крапка з комою чи символ нового рядка після кінцевої мітки не є обов'язковими. До прикладу, наступний код дозволений, починаючи з PHP 7.3.0:

Приклад #4 Продовження виразу після кінцевої мітки

<?php
$значення
= [<<<МІТКА
а
б
в
МІТКА, 'г ґ д'];
var_dump($значення);

В PHP 7.3 поданий вище приклад виведе:

array(2) {
  [0]=>
  string(14) "а
  б
    в"
  [1]=>
  string(8) "г ґ д"
}
Увага

Якщо назву мітки знайдено одразу після символу початку рядка, то навіть якщо це була частина тексту, вона розглядатиметься як кінцева мітка, що спричинить помилку ParseError.

Приклад #5 Кінцева мітка в тексті може викликати ParseError

<?php
$значення
= [<<<МІТКА
а
б
МІТКА помічає кінець тексту
МІТКА
, 'в г ґ'];

В PHP 7.3 поданий вище приклад виведе:

PHP Parse error:  syntax error, unexpected identifier "помічає", expecting "]" in example.php on line 5

Щоб уникнути цієї проблеми, безпечніше дотримуватися простого правила: не обирати мітку, яка може з'явитися в тексті.

Увага

До PHP 7.3.0, необхідно слідкувати за тим, щоб рядок з кінцевою міткою не містив нічого, крім самої мітки та крапки з комою (;) за нею. Це означає, що мітка не може відступати від початку рядка, а також не може бути жодних пропусків чи табуляції перед чи після крапки з комою. Також важливо, щоб символом перед кінцевою міткою був символ нового рядка, визначений локальною операційною системою. Це \n в системах UNIX, включно з macOS. Також цей символ має бути одразу після крапки з комою.

Якщо це правило порушено і кінцева мітка неправильна — вона не вважатиметься такою, а PHP продовжить шукати кінцеву мітку. Якщо до кінця поточного файлу мітку не буде знайдено, то на останньому рядку виникне синтаксична помилка.

Приклад #6 Недійсна мітка, до версії PHP 7.3.0

<?php
class foo {
public
$bar = <<<МІТКА
bar
МІТКА;
}
// Мітка повинна не мати відступів
?>

Приклад #7 Дійсна мітка, навіть до версії PHP 7.3.0

<?php
class foo {
public
$bar = <<<МІТКА
bar
МІТКА;
}
?>

Дані рядкового типу в синтаксисі Heredoc, які містять змінні, не можна використовувати для ініціалізації властивостей класу.

Текст Heredoc має ті ж особливості, що і рядок (string) в лапках, просто без лапок. Це означає, що лапки в Heredoc не потрібно екранувати, а перелічені вище екрановані послідовності досі можна використовувати. Змінні так само розкриваються, а складні змінні записуються тим же способом, що і в рядках (string).

Приклад #8 Вставлення інших рядків в Heredoc

<?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;
?>

Поданий вище приклад виведе:

Мене звати Петро. Я друкую Foo.
Зараз я друкую Bar2.
Має надрукуватись велика буква 'A': A

Також можливо використовувати Heredoc-синтаксис для передавання параметрів до функції:

Приклад #9 Heredoc в значеннях параметрів

<?php
var_dump
(array(<<<EOD
foobar!
EOD
));
?>

Можна задавати значення статичним змінним та властивостям/константам класу, використовуючи синтаксис Heredoc:

Приклад #10 Heredoc як статичне значення

<?php
// Поле класу
function foo()
{
static
$bar = <<<LABEL
Тут нічого цікавого...
LABEL;
}

// Властивість, константа класу
class foo
{
const
BAR = <<<FOOBAR
Приклад константи
FOOBAR;

public
$baz = <<<FOOBAR
Приклад властивості
FOOBAR;
}
?>

Початкову мітку Heredoc можна брати в лапки:

Приклад #11 Використання лапок в Heredoc

<?php
echo <<<"FOOBAR"
Привіт, світ!
FOOBAR;
?>

Nowdoc

Синтаксис nowdoc стосується рядків в апострофах, як heredoc — рядків в лапках, тобто працює схожим способом до heredoc, але без інтерполяції тексту всередині. Така конструкція прекрасно підходить для вставлення PHP-коду або великих частин тексту без необхідності їхнього екранування. Цей синтаксис має деякі спільні риси з конструкцією SGML <![CDATA[ ]]>, оскільки він оголошує блок тексту, який не підлягає аналізу.

Nowdoc починається з тої ж послідовності <<<, що й heredocs, але назва мітки, що йде далі, береться в апострофи, напр. <<<'EOT'. Усі правила щодо міток heredoc застосовуються також до міток nowdoc, особливо ті, що стосуються кінцевої мітки.

Приклад #12 Приклад тексту nowdoc

<?php
echo <<<'МІТКА'
Приклад тексту з кількома рядками
з використанням синтаксису nowdoc.
Зворотні косі риски завжди спиймаються буквально, напр. \\ і \'.
МІТКА;

Поданий вище приклад виведе:

Приклад тексту з кількома рядками
з використанням синтаксису nowdoc.
Зворотні косі риски завжди спиймаються буквально, напр. \\ і \'.

Приклад #13 Текст nowdoc зі змінними всередині

<?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;
?>

Поданий вище приклад виведе:

Мене звати $name. Я друкую $foo->foo.
Зараз я друкую {$foo->bar[1]}.
Має НЕ надрукуватись велику буква 'A': \x41

Приклад #14 Зі статичними даними

<?php
class foo {
public
$bar = <<<'EOT'
bar
EOT;
}
?>

Інтерполяція рядка

Якщо рядок (string) записано в лапках або в heredoc, то в нього можна вставляти змінні.

Є два способи запису: основний та розширений. Основний синтаксис є найпоширенішим і найзручнішим. Він надає можливість вбудувати змінну, значення масиву (array), або властивість об'єкта (object) в рядок (string) з невеликими зусиллями.

Основний синтаксис

Якщо трапляється знак долара ($), а після — символи, що є допустимими у назві змінної, то така послідовність вважається, власне, змінною, а в текст замість неї підставляється її рядкове значення.

<?php
$фрукт
= "персик";

echo
"Він з'їв $фрукт." . PHP_EOL;

?>

Поданий вище приклад виведе:

Він з'їв персик.

Формально, структура основного синтаксису підставлення змінних є такою:

рядкова-змінна::
     назва-змінної   (зміщення-або-властивість)?
   | ${   вираз   }

зміщення-або-властивість::
     зміщення-в-рядку
   | властивість-в-рядку

зміщення-в-рядкуg::
     [   назва   ]
   | [   назва-змінної   ]
   | [   цифровий-літерал   ]

властивість-в-рядку::
     ->  назва

назва-змінної::
     $   назва

назва::
     [a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*

Увага

Синтаксис ${ вираз } є застарілим, починаючи з PHP 8.2.0, оскільки його можна інтерпретувати як змінну змінної:

<?php
const foo = 'bar';
$foo = 'foo';
$bar = 'bar';
var_dump("${foo}");
var_dump("${(foo)}");
?>

В PHP 8.2 поданий вище приклад виведе:

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"

Поданий вище приклад виведе:

string(3) "foo"
string(3) "bar"
В такому випадку використовується розширений синтаксис інтерполяції рядка.

Зауваження: Якщо не вдається сформувати прийнятну назву змінної, то знак долара відтворюється в рядку буквально:

<?php
echo "Інтерполяція $ не відбувається\n";
echo
"Інтерполяція $\n не відбувається\n";
echo
"Інтерполяція $2 не відбувається\n";
?>

Поданий вище приклад виведе:

Інтерполяція $  не відбувається
Інтерполяція $
 не відбувається
Інтерполяція $2 не відбувається

Приклад #15 Інтерполяція значення першого виміру масиву або властивості

<?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.";
?>

Поданий вище приклад виведе:

Він випив яблучний сік.
Він випив апельсиновий сік.
Він випив фіолетовий сік.
Значення об'єкту: рядок.

Зауваження: Ключ масиву не повинен бути в лапках чи апострофах, і тому не можна посилатися на константу як на ключ за допомогою основного синтаксису. Для цього використовується розширений синтаксис.

Починаючи з PHP 7.1.0, підтримуються від'ємні цілочисельні індекси.

Приклад #16 Від'ємні цілочисельні індекси

<?php
$string
= 'string';
echo
"Символ з індексом -2 є \"$string[-2]\".", PHP_EOL;
$string[-3] = 'o';
echo
"Зміна символа з індексом -3 на \"o\" дає \"$string\".", PHP_EOL;
?>

Поданий вище приклад виведе:

Символ з індексом -2 є "n".
Зміна символа з індексом -3 на "o" дає "strong".

Для чогось складнішого використовується розширений синтаксис.

Розширений синтаксис

Розширений синтаксис дозволяє інтерполяцію змінних довільної форми.

Будь-яка скалярна змінна, елемент масиву або властивість об'єкту (static чи ні) з рядковим (string) представленням можна вставити в рядок за допомогою цього синтаксису. Вираз записується так, як він виглядає поза рядком (string) та береться в фігурні дужки ({ та }). Оскільки { не екранується, то цей синтаксис правильний тільки, якщо $ слідує одразу після {. Щоб буквально вивести послідовність {$, треба записати її так: {\$. Ось кілька прикладів для наочності:

<?php

const DATA_KEY = 'ключ-константа';
$great = 'фантастично';
$arr = [
'1',
'2',
'3',
[
41, 42, 43],
'ключ' => 'Індексоване значення',
'ключ-константа' => 'Від\'ємний ключ',
'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['ключ']}";


// Працює
echo "Це працює: {$arr[3][2]}";

echo
"Це працює: {$arr[DATA_KEY]}";

// Вставляючи елементи багатовимірних масивів в рядок, завжди потрібно брати їх
// у фігурні дужки
echo "це працює: {$arr['foo'][2]}";

echo
"Це працює: {$obj->values[3]->name}";

echo
"Це працює: {$obj->$staticProp}";

// Не працює, виводить: C:\folder\{фантастично}.txt
echo "C:\folder\{$great}.txt";

// Працює, виводить: C:\folder\фантастично.txt
echo "C:\\folder\\{$great}.txt";
?>

Зауваження: Оскільки розширений синтаксис підтримує довільні вирази, то використання змінних змінних — дозволено.

Зміна рядка та посимвольне редагування

Доступ до символа в рядку (string) можна отримати, як до елемента масиву (array), вказавши в квадратних дужках позицію символа, рахуючи від нуля, наприклад, $str[42] (43-й символ рядка str). Тобто, з цією метою потрібно вважати рядок (string) масивом (array) символів. Функції 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-байт.

Увага

Всередині інтерпретатора рядки є масивами байтів. Як наслідок, доступ до рядка або його редагування, як масиву, не є безпечним для багатобайтових кодувань і має здійснюватися лише з рядками в однобайтовому кодуванні, наприклад, ISO-8859-1.

Зауваження: Починаючи з PHP 7.1.0, застосування порожнього оператора індексу до порожнього рядка призводить до фатальної помилки. Раніше порожній рядок автоматично перетворювався на масив.

Приклад #17 Some string examples

<?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';

?>

String offsets have to either be integers or integer-like strings, otherwise a warning will be thrown.

Приклад #18 Example of Illegal String Offsets

<?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']));
?>

Поданий вище приклад виведе:

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)

Зауваження:

Accessing variables of other types (not including arrays or objects implementing the appropriate interfaces) using [] or {} silently returns null.

Зауваження:

Characters within string literals can be accessed using [] or {}.

Зауваження:

Accessing characters within string literals using the {} syntax has been deprecated in PHP 7.4. This has been removed in PHP 8.0.

Useful functions and operators

Strings may be concatenated using the '.' (dot) operator. Note that the '+' (addition) operator will not work for this. See String operators for more information.

There are a number of useful functions for string manipulation.

See the string functions section for general functions, and the Perl-compatible regular expression functions for advanced find & replace functionality.

There are also functions for URL strings, and functions to encrypt/decrypt strings (Sodium and Hash).

Finally, see also the character type functions.

Converting to string

A value can be converted to a string using the (string) cast or the strval() function. String conversion is automatically done in the scope of an expression where a string is needed. This happens when using the echo or print functions, or when a variable is compared to a string. The sections on Types and Type Juggling will make the following clearer. See also the settype() function.

A bool true value is converted to the string "1". bool false is converted to "" (the empty string). This allows conversion back and forth between bool and string values.

An int or float is converted to a string representing the number textually (including the exponent part for floats). Floating point numbers can be converted using exponential notation (4.1E+6).

Зауваження:

As of PHP 8.0.0, the decimal point character is always a period ("."). Prior to PHP 8.0.0, the decimal point character is defined in the script's locale (category LC_NUMERIC). See the setlocale() function.

Arrays are always converted to the string "Array"; because of this, echo and print can not by themselves show the contents of an array. To view a single element, use a construction such as echo $arr['foo']. See below for tips on viewing the entire contents.

In order to convert objects to string, the magic method __toString must be used.

Resources are always converted to strings with the structure "Resource id #1", where 1 is the resource number assigned to the resource 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 resource's type, use the get_resource_type() function.

null is always converted to an empty string.

As stated above, directly converting an array, object, or resource to a string does not provide any useful information about the value beyond its type. See the functions print_r() and var_dump() for more effective means of inspecting the contents of these types.

Most PHP values can also be converted to strings for permanent storage. This method is called serialization, and is performed by the serialize() function.

Details of the String Type

The string 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 0 (“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.)

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.

Given that PHP does not dictate a specific encoding for strings, one might wonder how string literals are encoded. For instance, is the string "á" equivalent to "\xE1" (ISO-8859-1), "\xC3\xA1" (UTF-8, C form), "\x61\xCC\x81" (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.

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 PHP’s functions:

  • 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, substr(), strpos(), strlen() or strcmp(). Another way to think of these functions is that operate on memory buffers, i.e., they work with bytes and byte offsets.
  • 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 htmlentities() and the majority of the functions in the mbstring extension.
  • Others use the current locale (see setlocale()), but operate byte-by-byte.
  • Finally, they may just assume the string is using a specific encoding, usually UTF-8. This is the case of most functions in the intl extension and in the PCRE extension (in the last case, only when the u modifier is used).

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 intl and mbstring 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.

add a note

User Contributed Notes 12 notes

up
108
gtisza at gmail dot com
12 years ago
The documentation does not mention, but a closing semicolon at the end of the heredoc is actually interpreted as a real semicolon, and as such, sometimes leads to syntax errors.

This works:

<?php
$foo
= <<<END
abcd
END;
?>

This does not:

<?php
foo
(<<<END
abcd
END;
);
// syntax error, unexpected ';'
?>

Without semicolon, it works fine:

<?php
foo
(<<<END
abcd
END
);
?>
up
24
BahmanMD
1 year ago
In PHP 8.2 using ${var} in strings is deprecated, use {$var} instead:

<?php
$juice
= "apple";

// Valid. Explicitly specify the end of the variable name by enclosing it in braces:
echo "He drank some juice made of {$juice}s.";
?>
up
25
lelon at lelon dot net
20 years ago
You can use the complex syntax to put the value of both object properties AND object methods inside a string. For example...
<?php
class Test {
public
$one = 1;
public function
two() {
return
2;
}
}
$test = new Test();
echo
"foo {$test->one} bar {$test->two()}";
?>
Will output "foo 1 bar 2".

However, you cannot do this for all values in your namespace. Class constants and static properties/methods will not work because the complex syntax looks for the '$'.
<?php
class Test {
const
ONE = 1;
}
echo
"foo {Test::ONE} bar";
?>
This will output "foo {Test::one} bar". Constants and static properties require you to break up the string.
up
15
Ray.Paseur sometimes uses Gmail
6 years ago
md5('240610708') == md5('QNKCDZO')

This comparison is true because both md5() hashes start '0e' so PHP type juggling understands these strings to be scientific notation. By definition, zero raised to any power is zero.
up
16
og at gams dot at
17 years ago
easy transparent solution for using constants in the heredoc format:
DEFINE('TEST','TEST STRING');

$const = get_defined_constants();

echo <<<END
{$const['TEST']}
END;

Result:
TEST STRING
up
14
steve at mrclay dot org
16 years ago
Simple function to create human-readably escaped double-quoted strings for use in source code or when debugging strings with newlines/tabs/etc.

<?php
function doubleQuote($str) {
$ret = '"';
for (
$i = 0, $l = strlen($str); $i < $l; ++$i) {
$o = ord($str[$i]);
if (
$o < 31 || $o > 126) {
switch (
$o) {
case
9: $ret .= '\t'; break;
case
10: $ret .= '\n'; break;
case
11: $ret .= '\v'; break;
case
12: $ret .= '\f'; break;
case
13: $ret .= '\r'; break;
default:
$ret .= '\x' . str_pad(dechex($o), 2, '0', STR_PAD_LEFT);
}
} else {
switch (
$o) {
case
36: $ret .= '\$'; break;
case
34: $ret .= '\"'; break;
case
92: $ret .= '\\\\'; break;
default:
$ret .= $str[$i];
}
}
}
return
$ret . '"';
}
?>
up
6
necrodust44 at gmail dot com
10 years ago
String conversion to numbers.

Unfortunately, the documentation is not correct.

«The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero).»

It is not said and is not shown in examples throughout the documentation that, while converting strings to numbers, leading space characters are ignored, like with the strtod function.

<?php
echo " \v\f \r 1234" + 1; // 1235
var_export ("\v\f \r 1234" == "1234"); // true
?>

However, PHP's behaviour differs even from the strtod's. The documentation says that if the string contains a "e" or "E" character, it will be parsed as a float, and suggests to see the manual for strtod for more information. The manual says

«A hexadecimal number consists of a "0x" or "0X" followed by a nonempty sequence of hexadecimal digits possibly containing a radix character, optionally followed by a binary exponent. A binary exponent consists of a 'P' or 'p', followed by an optional plus or minus sign, followed by a nonempty sequence of decimal digits, and indicates multiplication by a power of 2.»

But it seems that PHP does not recognise the exponent or the radix character.

<?php
echo "0xEp4" + 1; // 15
?>

strtod also uses the current locale to choose the radix character, but PHP ignores the locale, and the radix character is always 2E. However, PHP uses the locale while converting numbers to strings.

With strtod, the current locale is also used to choose the space characters, I don't know about PHP.
up
9
atnak at chejz dot com
20 years ago
Here is a possible gotcha related to oddness involved with accessing strings by character past the end of the string:

$string = 'a';

var_dump($string[2]); // string(0) ""
var_dump($string[7]); // string(0) ""
$string[7] === ''; // TRUE

It appears that anything past the end of the string gives an empty string.. However, when E_NOTICE is on, the above examples will throw the message:

Notice: Uninitialized string offset: N in FILE on line LINE

This message cannot be specifically masked with @$string[7], as is possible when $string itself is unset.

isset($string[7]); // FALSE
$string[7] === NULL; // FALSE

Even though it seems like a not-NULL value of type string, it is still considered unset.
up
6
php at richardneill dot org
11 years ago
Leading zeroes in strings are (least-surprise) not treated as octal.
Consider:
$x = "0123" + 0;
$y = 0123 + 0;
echo "x is $x, y is $y"; //prints "x is 123, y is 83"
in other words:
* leading zeros in numeric literals in the source-code are interpreted as "octal", c.f. strtol().
* leading zeros in strings (eg user-submitted data), when cast (implicitly or explicitly) to integer are ignored, and considered as decimal, c.f. strtod().
up
1
greenbluemoonlight at gmail dot com
4 years ago
<?php
\\Example # 10 Simple Syntax - Solution for the last "echo" line.

class people {
public
$john = "John Smith";
public
$jane = "Jane Smith";
public
$robert = "Robert Paulsen";

public
$smith = "Smith";
}

$people = new people();

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";
\
\Won't work
\\Outputs: Robert Paulsen greeted the two

/**Solution:**\

echo "$people->robert greeted the two $people->smith\x08s";

\\Will work
\\Outputs: Robert Paulsen greeted the two Smiths

?>
up
2
headden at karelia dot ru
15 years ago
Here is an easy hack to allow double-quoted strings and heredocs to contain arbitrary expressions in curly braces syntax, including constants and other function calls:

<?php

// Hack declaration
function _expr($v) { return $v; }
$_expr = '_expr';

// Our playground
define('qwe', 'asd');
define('zxc', 5);

$a=3;
$b=4;

function
c($a, $b) { return $a+$b; }

// Usage
echo "pre {$_expr(1+2)} post\n"; // outputs 'pre 3 post'
echo "pre {$_expr(qwe)} post\n"; // outputs 'pre asd post'
echo "pre {$_expr(c($a, $b)+zxc*2)} post\n"; // outputs 'pre 17 post'

// General syntax is {$_expr(...)}
?>
up
2
chAlx at findme dot if dot u dot need
16 years ago
To save Your mind don't read previous comments about dates ;)

When both strings can be converted to the numerics (in ("$a" > "$b") test) then resulted numerics are used, else FULL strings are compared char-by-char:

<?php
var_dump
('1.22' > '01.23'); // bool(false)
var_dump('1.22.00' > '01.23.00'); // bool(true)
var_dump('1-22-00' > '01-23-00'); // bool(true)
var_dump((float)'1.22.00' > (float)'01.23.00'); // bool(false)
?>
To Top