К основному содержимому

strict_types и строгая типизация PHP на проде

PHP · 29.09.2026

Что делает declare(strict_types=1) на самом деле

Директива declare(strict_types=1) должна стоять первой исполняемой строкой файла, сразу после открывающего тега <?php. Она не включает типизацию как таковую — типы параметров и возврата можно указывать и без неё. Она меняет только одно: как PHP ведёт себя, когда переданное значение не совпадает по типу с объявленным.

Без strict_types PHP пытается привести значение автоматически: строку "42" превратит в int 42, число 1 — в bool true. Со strict_types=1 любое несовпадение типа, кроме безопасного расширения int в float, завершается исключением TypeError сразу в момент вызова функции, а не где-то внутри неё после нескольких строк логики.

Слабая типизация: пример неявного приведения

Функция ниже объявляет параметр int, но без strict_types PHP примет и строку, и число с плавающей точкой, молча обрезав дробную часть.

function applyDiscount(int $percent): float {
    return 100 - $percent;
}

echo applyDiscount("15abc"); // сработает как applyDiscount(15), без ошибки

Строка "15abc" не число, но PHP в нестрогом режиме отрежет часть, которая похожа на число, и выполнит функцию. Ошибка проявится не здесь, а там, где результат окажется неожиданно неверным — искать её придётся уже по логам, как описано в статье о разборе логов PHP.

Со strict_types=1: та же ошибка ловится сразу

Тот же код с добавленной директивой в начале файла ведёт себя иначе — вместо тихого приведения происходит явный отказ.

declare(strict_types=1);

function applyDiscount(int $percent): float {
    return 100 - $percent;
}

echo applyDiscount("15abc");
// TypeError: applyDiscount(): Argument #1 ($percent) must be of type int, string given

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

Типы свойств, параметров и возврата: примеры

КонструкцияПримерЧто проверяет strict_types
Тип параметраfunction f(int $x)тип аргумента при вызове
Тип возвратаfunction f(): stringтип значения после return
Тип свойства классаprivate float $priceтип при присваивании полю
Nullable-типfunction f(?int $x)допускает int или null, не строку

Nullable-типы и union-типы вида int|string работают со strict_types так же строго: любое значение, не входящее в объявленный список, вызывает TypeError.

Где строгая типизация ломает существующий код

  • Данные из $_GET и $_POST всегда приходят строками — их нужно явно приводить через (int) перед передачей в типизированную функцию.
  • Значения из PDO по умолчанию тоже строки, даже для числовых колонок — без явного приведения strict_types выбросит TypeError.
  • Старые библиотеки без объявленных типов параметров продолжают работать как раньше, strict_types их не затрагивает.
  • JSON после json_decode отдаёт числа как int или float в зависимости от содержимого — проверяйте тип перед передачей дальше.
  • Тесты, написанные с расчётом на автоматическое приведение типов, начинают падать и требуют явных приведений в моках.

Итог: чек-лист внедрения strict_types

  • declare(strict_types=1) стоит первой строкой после <?php в каждом файле проекта.
  • Все входящие данные из $_GET, $_POST и PDO приводятся к нужному типу явно, а не полагаются на автоприведение.
  • Параметры и возвращаемые значения публичных методов имеют объявленные типы, включая nullable и union.
  • Новый TypeError отслеживается через error_log, а не через display_errors на проде.
  • Изменение внедрено постепенно, по одному модулю, с прогоном тестов после каждого файла.
← Назад в базу знаний Задать вопрос поддержке