Привет, Хабр. В преддверии старта онлайн-курса «PHP-разработчик» подготовили традиционный перевод материала. Предлагаем также посмотреть запись прошедшего демо-занятия «Экосистема PHP».


Многие современные языки программирования поддерживают различные способы использования различных символов, таких как обычные английские латинские буквы, числа, символы, эмодзи и различные специальные символы, такие как символ новой строки или символ табуляции.

Большинство символов можно просто набрать с клавиатуры и использовать в коде PHP в их исходном виде. Например, $string = "php.watch" - это полностью допустимая строка в PHP, а $num = 42 - допустимое число. Также можно использовать многобайтные символы (для хранения которых требуется более одного байта), например, этот совершенно допустимый эмодзи: $emoji = "?".

PHP, наряду со многими другими языками программирования, поддерживает определенное количество escape-последовательностей для использования различных символов, которые не могут быть набраны с обычной клавиатуры, не могут быть представлены в текстовой форме (например, невидимые символы или различные управляющие символы) или иным образом не считываются. Эти символы используют escape-последовательности, которые распознает PHP.

Что касается чисел, PHP поддерживает стандартные десятичные числа, но также может использовать и другие нотиции, такие как двоичное, восьмеричное, шестнадцатеричное и даже научное (scientific) представление. Они могут сделать код более читаемым и понятным в зависимости от контекста.

Двойные кавычки и Heredoc

В PHP строка с двойными кавычками ("string") или Heredoc (смотрите ниже) поддерживает escape-последовательности и интерполяцию переменных.

PHP будет пытаться интерполировать переменные, если строковый литерал находится внутри строки с двойными кавычками или Heredoc.

$name = 'John';
echo "Hi $name"; // "Hi John"
$name = 'John';
echo <<<HEREDOC
Hi $name
HEREDOC;
// "Hi John"

Альтернативно (и желательно) интерполируемые переменные могут быть выделены фигурными скобками, так они будут выглядеть более удобочитаемыми:

$name = 'John';
echo "Hi {$name}"; // "Hi John"

Строки в одинарных кавычках ('string') и синтаксис Nowdoc не интерполируют переменные:

$name = 'John';
echo 'Hi $name'; // "Hi $name"
$name = 'John';
echo <<<'NOWDOC'
Hi $name
NOWDOC;
// "Hi $name"

Только строки в двойных кавычках и Heredoc поддерживают escape-символы.

Экранирование символов

Поскольку PHP интерпретирует и интерполирует специальные символы внутри строковых литералов в двойных кавычках и heredoc, знак обратной косой черты (\) используется как «escape-символ».

Например, использование \$name вместо $name не даст PHP интерполировать переменную $name.

$name = 'John';
echo "Hi \$name"; // "Hi $name"

Использование второго символа обратной косой черты предотвращает преобразование первого символа обратной косой черты в escape-символ.

$name = 'John';
echo "Hi \\$name"; // "Hi \John"

PHP поддерживает несколько специальных escape-последовательностей для специальных символов. В приведенном выше примере \$ считается escape-последовательностью, потому что он отменяет интерполяцию PHP, заставляя PHP буквально использовать символ $.

Символы табуляции: \t и \v

Возможно, самые простой из управляющих символов - это символ табуляции. Символ табуляции (по нажатию клавиши tab) можно использовать внутри строкового литерала, но использование \t вместо визуального пропуска делает его наглядным. Использование \t вместо буквального символа табуляции также позволяет избежать автоматической замены символов табуляции на пробелы в различных IDE.

echo "Foo\tBar";
Foo Bar

\v - это вертикальная табуляция. На поддерживаемых терминалах символ вертикальной табуляции переходит к следующему символу в следующей строке:

echo "Foo\vBar\vBaz";
Foo
   Bar
      Baz

Новые строки: \r и \n

\r («возврат каретки») и \n («перевод строки») являются символами новой строки.

Исторически так сложилось, что различные системы начали использовать либо \r, либо \n, и даже Windows использует \r\n. Например, Linux и MacOS по умолчанию используют символ «перевода строки» (\n) в качестве символа новой строки, тогда как Windows использует комбинацию \r\n (возврат каретки, за которым следует перевод строки). Старые системы MacOS использовали в качестве символа новой строки \r.

PHP имеет константу PHP_EOL, которая всегда ссылается на системный символ новой строки.

echo "Left\nLeft\nRight\nRight";
Left
Left
Right
Right

Escape-символ: \e

Escape-символы часто используется для отправки управляющих последовательностей ANSI в терминал. Например, \e, за которым следует [32m, указывает терминалу изменить цвет на зеленый, а [33m - на желтый.

echo "\e[32mGreen text\e[0m \e[33mYellow text\e[0";

Если приведенный выше фрагмент выполняется в терминале, который поддерживает управляющие последовательности ANSI, он интерпретирует его и изменяет текст:

Символ новой страницы: \f

Символ новой страницы - это управляющий символ ASCII для обозначения конца страницы. С его помощью принтеры могут вывести текущую страницу и начать с верхней части следующей. Когда \f передается на дисплейный терминал, он может результировать в очистке экрана, хотя это очень редкое поведение для большинства программ эмуляции терминала.


Восьмеричные escape-последовательности символов ASCII 

PHP поддерживает экранирование восьмеричного числа в его соответствующий ASCII символ.

Например, ASCII символ P равен 80 в десятичной системе (смотрите диаграмму). 80 из десятичной системы счисления в переводе в восьмеричную - 120.

Для символа P можно использовать восьмеричную escape-последовательность:

echo "\120";

P

Любой базовый символ ASCII можно представить с помощью такой записи:

echo "\120\110\120\56\127\141\164\143\150";

PHP.Watch

Любое значение в диапазоне от \0 до \377 будет интерпретироваться как восьмеричная escape-последовательность ASCII символа.

Обратите внимание, что числа для расширенных символов ASCII (от 128 до 255) несовместимы с UTF-8. PHP считает значение 128 (восьмеричное: 200; шестнадцатеричное: 80) недопустимым, поскольку оно не является допустимым значением UTF-8.

Хотя PHP принимает такие значения, они считаются недопустимыми символами в контексте UTF-8.

Шестнадцатеричные escape-последовательности символов ASCII

Подобно восьмеричным escape-последовательностям символов, PHP также допускает использование шестнадцатеричных чисел в escape-последовательности символов с префиксом \x .

Допускается только один байт, что подразумевает допустимый диапазон от x0 до xFF. Однако ограничение UTF-8 по-прежнему присутствует, и только значения до x80 будут считаться допустимыми символами.

Кроме того, шестнадцатеричные символы не чувствительны к регистру (т.е. AF равно af и aF).

ASCII P - 80, что равно x50:

echo "\x50";

P

Тот же "PHP.Watch" пример можно переписать с помощью шестнадцатеричных escape-последовательностей:

echo "\x50\x48\x50\x2E\x57\x61\x74\x63\x68";

PHP.Watch

Escape-последовательности символов Unicode

PHP поддерживает использование любого Unicode символа с префиксом \u и шестнадцатеричным значением code point внутри фигурных скобок.

echo "\u{1F418} - \u{50}\u{48}\u{50}\u{2E}\u{57}\u{61}\u{74}\u{63}\u{68}";

? - PHP.Watch

PHP выдаст ошибку парсера, если символ Unicode превышает значение 10FFFF:

echo "\u{10FFFF1}"

Invalid UTF-8 codepoint escape sequence: Codepoint too large on line ...

 10FFFF является верхним пределом, потому что спецификация UTF-8 объявляет диапазон от U+0000 до U+10FFFF.

В предыдущей версии этой статьи верхний предел неверно упоминался как FFFFF, что было исправлено на 10FFFF. Спасибо Саре Големон за то, что она указала на это.


Форму записи Unicode \u{} можно использовать качестве escape-последовательности для любого символа. Вот несколько примеров:

Символ

Code point (Dec)

Code point (Hex)

Escape-последовательность Unicode

A

65

41

"\u{41}"

B

66

42

"\u{42}"

$

36

24

"\u{24}"

8364

20AC

"\u{20AC}"

\n (перевод строки)

10

A

"\u{A}"

\r (возврат каретки)

13

D

"\u{D}"

\t (горизонтальная табуляция)

9

9

"\u{9}"

\v (вертикальная табуляция)

11

B

"\u{B}"

\e (управляющий символ)

27

1B

"\u{1B}"

\f (новая страница)

12

C

"\u{C}"

?

128024

1F418

"\u{1F418}"

?

3461

D85

"\u{D85}"


Двоичные строки

Несколько лет назад PHP 5.2.1 представил новый строковый синтаксис, названный «двоичными строками» (binary strings). Это с натяжкой можно было назвать синтаксисом, и он был задуман в рамках улучшение прямой совместимости с грядущим PHP 6.

Синтаксис заключался в добавлении префикса b к строкам в одинарных/двойных кавычках, чтобы PHP мог распознать это как двоичную строку.

echo b'Foo';

Foo

Функции is_binary, is_unicode и is_buffer должны были различать двоичные строки и строки Unicode в PHP 6, но они так и не добрались до следующей версии PHP 7. Однако синтаксис двоичной строки все-таки попал в PHP 7 и поддерживается в PHP 8.

Синтаксис двоичных строк не имеет какой-либо специальной функциональности и служит только для того, чтобы быть историческим пережитком, внезапным вопросом на собеседовании, интересным фактом для статей по PHP и сбивать с толку других PHP разработчиков.

Этот синтаксис не является устаревшим и не планируется к удалению в будущей версии PHP.


Числовые нотации

При использовании числовых литералов в PHP-скриптах PHP по умолчанию ожидает десятичные значения. Однако PHP также допускает другие числовые нотации, такие как двоичные числа, восьмеричные числа, шестнадцатеричные числа и научная нотация.

Начиная с PHP 7.4, PHP также позволяет разделять разряды нижнем подчеркиванием для лучшей читаемости длинных чисел.

Двоичная нотация

Любой числовой литерал, начинающийся с префикса 0b, будет считаться двоичным числом.

$number_binary  = 0b101010;

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

$number_binary = 0b10_1010;

0b101010  === 42; // true

0b10_1010 === 42; // true

Восьмеричная нотация

PHP принимает восьмеричные числовые значения с префиксом 0. Начиная с PHP 8.1, PHP также поддерживает явную восьмеричную числовую нотацию с префиксами 0O и 0o.

$number_octal = 052; // === Десятичное 42
$number_octal = 0o52; // === Десятичное 42
$number_octal = 0O52; // === Десятичное 42

Шестнадцатеричная нотация

Числа интерпретируются в шестнадцатеричные с помощью префиксов \0X и \0x.

$number_hex = 0x2A; // === Десятичное 42
$number_hex = 0X2A; // === Десятичное 42

Научная нотация (Scientific Notation)

PHP также поддерживает научную "E-нотацию" для значений с плавающей запятой.

$number_float = 42E1;

E-нотация эквивалентна 42 * 10^0 (10 в степени 0). Обратите внимание, что во многих языках программирования (включая PHP) оператор ^ используется для XOR, а для возведения в степень используется ** .

Преимущество удобочитаемости научной нотации более выражено для очень точных или больших чисел.

$planck_constant    = 6.62607004E-34;
$avogadros_constant = 6.022140857E+23;
3.844E5 === 3.844 * 10**5 === 384400.0; // true

PHP поддерживает различные формы escape-последовательностей и числовых обозначений. Недавно он добавил явную восьмеричную числовую нотацию с префиксами 0O/0o(PHP 8.1)и числовые разделители разрядов (PHP 7.4).

Обратите внимание, что эти escape-последовательности и числовые обозначения не интерпретируются при считывании пользовательского ввода. Например, преобразование числа, разделенного нижним подчеркиванием, к целому числу не будет учитывать использование этой новой фичи PHP для строк, предоставленных пользователем.

var_dump((int) "2_34_5");
// int(2)

var_dump((int) "0xabcd");
// int(0)

Escape-последовательности в пользовательском вводе, также не учитываются. Например, если форма содержит "\43", это значение будет использоваться как есть, без интерпретации как восьмеричная escape-последовательность для символа. А $str = "\43" выдаст "#", потому что в исходных файлах PHP это работает.


Узнать подробнее о курсе «PHP-разработчик»

Смотреть запись прошедшего демо-занятия «Экосистема PHP».