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.
Как писать строго
declare(strict_types=1);в каждом файле.- Типы у параметров, возвращаемых значений и свойств (typed properties с PHP 7.4).
readonlyиenum(PHP 8.1) вместо «магических» строк и изменяемых DTO.- 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?