declare(strict_types=1)
В режиме приведения PHP помогает: строка '5' сама становится числом 5. Но иногда такая помощь прячет ошибку. Если число пришло строкой, его, скорее всего, прочитали из формы или из файла и забыли преобразовать, а программа молча работает дальше.
Вернёмся к автомату. В прошлом уроке у него стоял услужливый служащий, который менял бумажку '5' на монету 5. Строка declare(strict_types=1); отпускает служащего: прорезь принимает только монету нужной формы.
Такая строка — директива: указание PHP, как читать этот файл. Директива strict_types=1 включает строгий режим: PHP не приводит аргументы и требует точного типа.
<?php
declare(strict_types=1);
function area(float $side): float
{
return $side * $side;
}
echo area(1.5), "\n"; // 2.25
echo area(3), "\n"; // 9Давайте разберём программу по шагам:
declare(strict_types=1);включает строгий режим для этого файла. Директиву ставят первой инструкцией, сразу после<?php.area(1.5)передаётfloat, и тип совпадает с объявленным.area(3)передаётint, и вызов всё равно работает: целое число в параметрfloat— единственная поблажка строгого режима.- Результат
9.0— дробное число без дробной части, поэтомуechoпечатает его как9.
Что отвергает строгий режим
Строку с числом строгий режим уже не пропускает:
echo area('3'), "\n"; // ✗Fatal error: Uncaught TypeError: area(): Argument #1 ($side) must be of type float, string givenВ строгом режиме параметр int принимает аргументы так:
'4'—TypeError, хотя в строке записано число;2.0—TypeError, хотя дробной части нет;true—TypeError;4— проходит: тип совпадает.
Строгий режим действует и на встроенные функции: в таком файле strlen(123) тоже бросает TypeError.
Здесь картинка с автоматом упрощает. Строгий автомат всё-таки пропускает целую монету 3 в прорезь для дробных, int в float. В обратную сторону поблажки нет: 2.0 в параметр int не пройдёт.
Где действует директива
Программы побольше состоят из нескольких файлов, и директива действует только в том файле, где написана. Главное правило: важно, где стоит вызов, а не где объявлена функция.
- Функция объявлена в файле без директивы, а вызов стоит в файле с ней: аргументы проверяются строго.
- Функция объявлена в файле с директивой, а вызов стоит в файле без неё: PHP приводит аргументы, как обычно.
- Результат функции проверяется по режиму того файла, где функция объявлена.
- Директива не переходит в другие файлы: в каждом файле её пишут заново.
Этот вопрос часто задают на собеседовании: в каком файле должна стоять директива, чтобы вызов проверялся строго? Ответ — в файле, где написан вызов.
Зачем включать строгий режим
Новые проекты обычно ставят директиву в начало каждого файла. Причины:
- ошибка видна там, где появилась: строка вместо числа останавливает вызов, а не превращается молча в число;
- редакторы и программы-анализаторы кода опираются на точные типы и находят ошибки ещё до запуска;
- код читается однозначно: какой тип объявлен, такой и придёт.
В остальных примерах курса директивы нет — так видно, как PHP приводит типы. В своих проектах включайте её.
Частая ошибка
Директиву поставили не первой инструкцией:
<?php
echo 'start', "\n";
declare(strict_types=1); // ✗Fatal error: strict_types declaration must be the very first statement in the scriptPHP проверяет это до запуска, поэтому файл не выполняется вовсе — не напечатается даже start. Исправление — поставить директиву сразу после <?php, перед любым другим кодом.
Главное
declare(strict_types=1);первой инструкцией файла включает строгий режим: аргументы не приводятся.- В строгом режиме
'4'и2.0для параметраintдаютTypeError, аintдля параметраfloatпроходит. - Строгость вызова решает файл, где написан вызов, а не файл, где объявлена функция.