Урок по треку PHP 7 мин

Типы и строгая типизация в PHP

Скалярные типы, приведение и сравнения в PHP 8, strict_types, union и nullable.

PHP динамически типизирован и умеет неявно приводить типы. На собесе почти всегда дают пару сравнений и спрашивают, что изменилось в PHP 8 и как писать строгий код.

Типы данных

  • Скалярные: int, float, string, bool.
  • Составные: array, object, callable, iterable.
  • Специальные: null, resource.
  • Для объявлений: mixed, void, never, static, self, объединения int|string, пересечения A&B, DNF (A&B)|null.

int 64-битный. При выходе за PHP_INT_MAX результат становится float, а не «заворачивается»: PHP_INT_MAX + 1 это float(9.2233720368547758E+18). Для точной арифметики bcmath или gmp.

Сравнения

=== сравнивает тип и значение, == сначала приводит типы. В PHP 8 правила сравнения числа со строкой изменились:

0 == "abc";    // PHP 8: false (число приводится к строке "0"), PHP 7: true
"1" == "01";   // true: обе строки числовые, сравниваются как числа
"10" == "1e1"; // true
null == false; // true

Нестрого сравнивают и функции: in_array, array_search (у обеих есть третий параметр strict), а также switch. Выражение match сравнивает строго.

Ложные значения

false, 0, 0.0, "", "0", [], null. Всё остальное истинно, включая "0.0" и " ". Ловушка: if ($count) не отличит ноль от отсутствия значения.

Числовые строки в PHP 8

"12 " + 1;       // 13: пробелы в конце допустимы
"5 apples" + 10; // 15 и Warning: A non-numeric value encountered
"apples" + 10;   // TypeError: Unsupported operand types
(int) "12abc";   // 12 без предупреждений: явное приведение молчит

Операторы для null

  • ?? возвращает правую часть, если левой нет или она null, без предупреждений о неопределённых ключах. Есть ??=.
  • ?: срабатывает на любое ложное значение: для 0 и "" тоже.
  • ?-> (PHP 8.0) обрывает цепочку вызовов на null.

strict_types

declare(strict_types=1);

function total(int $qty, float $price): float { return $qty * $price; }

total("3", 9.9); // TypeError в строгом режиме, без него "3" приведётся к 3

Директива действует на вызовы из файла, где она объявлена, и только для скалярных типов. Исключение: int можно передать туда, где ожидают float.

Как писать строго

  1. declare(strict_types=1); в каждом файле.
  2. Типы у параметров, возвращаемых значений и свойств (typed properties с PHP 7.4).
  3. readonly и enum (PHP 8.1) вместо «магических» строк и изменяемых DTO.
  4. PHPStan или Psalm в CI, дженерики в PHPDoc: @param list<User> $users.

Частые ошибки

  • == там, где нужно ===, особенно с "0" и null.
  • in_array без true.
  • Деньги во float: 0.1 + 0.2 != 0.3. Считайте в копейках.
  • Надеяться, что (int) проверит формат строки.

Что спросят на собесе

  • Чем == отличается от ===, что изменилось в PHP 8?
  • Какие значения ложные?
  • Что делает declare(strict_types=1) и на что он влияет?
  • Что будет при переполнении int?
  • Как устроена система типов современного PHP?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.