• Время чтения ~1 мин
  • 24.05.2023

Введение

Если вы разработчик PHP, вы, вероятно, видели инструкцию declare(strict_types=1) в начале некоторых файлов PHP.

Когда я впервые увидел это заявление, я понятия не имел, что оно делает. Я предположил, что это был какой-то комментарий или, может быть, какой-то старый синтаксис PHP, который был до моего времени, но я ошибался (очень ошибался!).

В этой статье мы рассмотрим, что declare(strict_types=1) такое и как это может помочь вам повысить безопасность типов вашего PHP-кода.

Что такое declare(strict_types=1)?

declare(strict_types=1) is a statement that enforces strict typing in PHP applications.

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

Давайте возьмем простой пример, который не использует declare(strict_types=1):

function add(int $a, int $b): int
{
    return $a + $b;
}

Теперь предположим, что мы вызвали эту функцию со строковыми параметрами:

echo add('1', '2');
 
// Output:
// 3

PHP will happily convert the string parameters to integers and return the result 3.

В некоторых случаях вас может полностью устраивать такое поведение. Но это может иметь некоторые непредвиденные последствия, которых вы не ожидали, и это может привести к ошибкам в вашем приложении.

Однако давайте представим, что мы хотели использовать declare(strict_types=1) в этом примере. Мы могли бы сделать это, добавив следующий оператор в верхней части файла:Теперь, если мы вызовем add функцию со строковыми параметрами, PHP выдаст ошибку:

declare(strict_types=1);
 
function add(int $a, int $b): int
{
    return $a + $b;
}

echo add('1', '2');
 
// Output:
// Fatal error: Uncaught TypeError: Argument 1 passed to add() must be of the type int, string given
As we can see here, PHP has thrown an error because the add function expected integers to be passed, but received strings instead.

Точно так же PHP также будет выдавать ошибки, если включена строгая проверка типа, и мы попытаемся вернуть неправильный тип данных из метода. Например, предположим, что наша add функция теперь принимает числа с плавающей запятой вместо целых чисел и что у нас не включена строгая проверка типа:Тогда мы могли бы вызвать функцию следующим образом:

function add(float $a, float $b): int
{
    return $a + $b;
}

Ответ, который мы должны были получить,

echo add(1.25, 2.25);
 
// Output:
// 3
Did you spot the problem in the output?

- 3.5. Однако, поскольку мы определили возвращаемый тип как int, мы преобразовали число с плавающей запятой (которое должно было быть возвращено) в целое число и потеряли точность. Как вы можете себе представить, это может вызвать некоторые проблемы в других частях нашего приложения, где мы используем этот результат, и, возможно, потребуется точность.

Теперь давайте исправим эту проблему с помощью declare(strict_types=1):Затем мы могли бы вызвать функцию следующим образом:

declare(strict_types=1);
 
function add(float $a, float $b): int
{
    return $a + $b;
}
Ответ, который мы должны были получить,
echo add(1.25, 2.25);
 
// Output:
// Fatal error: Uncaught TypeError: add(): Return value must be of type int, float returned

Как мы видим, включив строгую проверку типа, мы можем обнаружить, что функция не возвращает правильный тип данных. Это здорово, потому что это может указывать на возможную ошибку в нашем коде, о которой мы не знали. Затем мы могли бы предпринять необходимые шаги, чтобы:

  • Обновите типы возвращаемых данных, если они неверны
  • Обновите подсказки по типу, если они неверны
  • Обновите текст функции, чтобы вернуть правильный тип данных, если он неверен
  • Исправьте все ошибки в коде, вызывающем функцию, которая может передавать ей неправильный тип данных

Стоит ли использовать declare(strict_types=1)?

Лично я думаю, что это хорошая идея для использования declare(strict_types=1) во всех ваших файлах PHP. Раньше я думал, что достаточно просто иметь подсказки типов и возвращаемые типы, чтобы обеспечить передачу правильных типов данных, но с тех пор я изменил свое мнение. Я чувствую себя гораздо увереннее в своем коде, когда использую declare(strict_types=1) его, и обнаружил несколько ошибок в результате его использования (в частности, при добавлении его в старые кодовые базы).

С тех пор, как я узнал об этом, я взял за привычку использовать его в каждом новом файле PHP, который я создаю. Фактически, я обновил все шаблоны в моей настройке PhpStorm , чтобы они автоматически включались в верхнюю часть каждого файла, который я создаю. Например, вот шаблон, который используется при создании нового класса PHP:Это действительно удобно,

 <?php
 
 declare(strict_types=1);
 
 #parse("PHP File Header.php")
 
 #if (${NAMESPACE})
 namespace ${NAMESPACE};

 #end
class ${NAME} {

}

потому что побуждает меня продолжать использовать declare(strict_types=1) без необходимости вносить какие-либо изменения вручную после создания файла (что я определенно забуду сделать!).

Для любого из моих читателей Laravel вы также можете опубликовать заглушки , которые используются для создания файлов PHP при выполнении команд Artisan, таких как php artisan make:controller. Опубликовав заглушки, вы можете редактировать их и добавлять declare(strict_types=1) в топ. Это означает, что файлы, создаваемые с помощью команд Artisan, будут создаваться с уже включенной более строгой безопасностью типов.

Конечно, если вы собираетесь добавить более строгую проверку типов к существующим файлам, я настоятельно рекомендую сначала иметь качественный набор тестов. Возможно, ваш PHP-код позволял передавать неправильные типы данных без каких-либо ошибок. Но, включив строгую проверку типов, ваш код станет гораздо менее снисходительным и может начать выдавать ошибки. Это может привести к тому, что приложение сломается неожиданным для пользователей образом.

Вы также можете обнаружить, что вам нужно выполнить рефакторинг некоторого кода, чтобы сделать его совместимым с declare(strict_types=1). Хотя я бы не считал это чем-то плохим. Вместо этого я бы рассматривал это как возможность улучшить качество вашего кода.

Чтобы помочь с процессом добавления declare(strict_types=1) в ваш код, вы можете использовать такой инструмент, как PHPStan, который может обнаружить эти несоответствия типов для вас.

Заключение

Надеемся, что эта статья дала вам краткий обзор того, что declare(strict_types=1) такое и как это может помочь вам повысить безопасность типов вашего PHP-кода.

Если вам понравилось читать этот пост, я хотел бы услышать об этом. Точно так же, если у вас есть какие-либо отзывы для улучшения будущих, я также хотел бы это услышать.

Вам также может быть интересно ознакомиться с моей 220+ страничной электронной книгой «Battle Ready Laravel», в которой более подробно рассматриваются аналогичные темы.

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

Продолжайте создавать потрясающие вещи! 🚀

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Об авторе CrazyBoy49z
WORK EXPERIENCE
Контакты
Ukraine, Lutsk
+380979856297