strict_types в PHP: почему важен файл вызывающего кода
Где действует strict_types в PHP и почему проверка пользовательского ввода всё равно нужна.
- Пользовательский вводРазбираем строковые значения явно
- Файл вызоваdeclare(strict_types=1) задаёт строгий вызов
- ФункцияПолучает аргументы подходящих скалярных типов
Форма передала строку «12», а функция ждёт int. В обычном режиме PHP может преобразовать значение автоматически. strict_types меняет правила передачи скалярных аргументов, причём важен файл вызывающего кода. Отделим разбор данных формы от расчёта и проверим, что происходит на границе между файлами.
Отделяем ввод от вычисления
<?php
declare(strict_types=1);
function total(int $quantity, int $unitPrice): int {
return $quantity * $unitPrice;
}
$raw = '3';
$quantity = filter_var($raw, FILTER_VALIDATE_INT,
['options' => ['min_range' => 1, 'max_range' => 100]]);
if ($quantity === false) {
throw new InvalidArgumentException('Количество вне диапазона');
}
echo total($quantity, 250);
// total('3', 250); // TypeError в этом файлеЗдесь строка не становится числом случайно внутри расчёта. Проверка входа подтверждает формат и диапазон, после чего функция получает ожидаемый тип. Результат примера равен семистам пятидесяти условным единицам. Представление цены целым числом удобно для этого упражнения; правила валюты, округления и предельного размера суммы остаются отдельным контрактом и не возникают автоматически благодаря декларации типов.
Что строгий режим не проверяет
Строгая типизация скалярных вызовов не превращает массив в описанную схему и не проверяет бизнес-ограничения. Целое число минус десять соответствует int, хотя для количества оно запрещено. Строка из HTTP-запроса остаётся строкой до явной обработки. Кроме того, для ожидаемого float допустим аргумент int. Не стройте проверку безопасности на предположении, что любое преобразование полностью отключено.
Директива должна находиться в начале PHP-файла. Возможности этого примера доступны в PHP 7 и не требуют синтаксиса PHP 8. При постепенном переходе проекта перечислите файлы, которые делают важные вызовы, и начните с них. Если один и тот же метод вызывается из строгого и нестрогого файла, поведение скалярных аргументов может отличаться. Это причина проверять реальные точки входа, а не только определение функции.
Вызовы со strict_types и без него
Вынесите функцию в отдельный файл и вызовите её из двух файлов: со strict_types и без него. Передайте строку с цифрой и целое число, посмотрите, где возникнет TypeError. Затем проверьте ноль и превышение лимита во входном обработчике. Это две разные проверки: тип аргумента и допустимое для приложения значение.
