Что строгие типы делают в PHP?

149

Я видел следующую новую строку в PHP 7, но никто толком не объясняет, что это значит. Я погуглил, и все, о чем они говорят, это то, включите ли вы это или нет, как в опросах.

declare(strict_types = 1);

Что оно делает? Как это повлияет на мой код? Я должен сделать это?

Некоторое объяснение было бы неплохо.

sufuko
источник
5
. взгляните на это тоже php.net/manual/en/… для директивы
strict_types

Ответы:

155

Из блога Treehouse :

В PHP 7 мы добавили скалярные типы. В частности: int, float, string и bool.

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

По умолчанию объявления скалярных типов не являются строгими, что означает, что они будут пытаться изменить исходный тип, чтобы он соответствовал типу, указанному в объявлении типа. Другими словами, если вы передадите строку, начинающуюся с числа, в функцию, требующую числа с плавающей запятой, она захватит число с самого начала и удалит все остальное. Передача числа с плавающей запятой в функцию, которая требует int, станет int (1).

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

Строгие типы отключены ( eval ):

<?php

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

  echo AddIntAndFloat(1.4, '2');
  /*
  * without strict typing, PHP will change float(1.4) to int(1)
  * and string('2') to float(2.0) and returns int(3)
  */

Можно включить строгий режим для каждого файла. В строгом режиме будет принята только переменная с точным типом объявления типа, в противном случае будет сгенерирована ошибка TypeError. Единственное исключение из этого правила - целое число может быть присвоено функции, ожидающей число с плавающей точкой. На вызовы функций из внутренних функций объявление strict_types не повлияет.

Чтобы включить строгий режим, оператор declare используется с объявлением strict_types:

Включены строгие типы ( eval ):

<?php declare(strict_types=1);

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

  echo AddIntAndFloat(1.4,'2');
  // Fatal error: Uncaught TypeError: Argument 1 passed to AddIntAndFloat() must be of the type int, float given
  echo AddIntAndFloat(1,'2');
  // Fatal error: Uncaught TypeError: Argument 2 passed to AddIntAndFloat() must be of the type float, string given

  // Integers can be passed as float-points :
  echo AddIntAndFloat(1,1);
  // Fatal error: Uncaught TypeError: Return value of AddIntAndFloat() must be of the type integer, string returned

Рабочий пример:

<?php

declare(strict_types=1);

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

$float = AddFloats(1.5,2.0); // Returns 3.5

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

$int = AddFloatsReturnInt($float,1.5); // Returns 5

function Say(string $message): void // As in PHP 7.2
{
    echo $message;
}

Say('Hello, World!'); // Prints "Hello, World!"

function ArrayToStdClass(array $array): stdClass
{
    return (object) $array;
}

$object = ArrayToStdClass(['name' => 'azjezz','age' => 100]); // returns an stdClass

function StdClassToArray(stdClass $object): array
{
    return (array) $object;
}

$array = StdClassToArray($object); // Returns array

function ArrayToObject(array $array): object // As of PHP 7.2
{
    return new ArrayObject($array);
}

function ObjectToArray(ArrayObject $object): array
{
    return $object->getArrayCopy();
}

var_dump( ObjectToArray( ArrayToObject( [1 => 'a' ] ) ) ); // array(1 => 'a');
Саиф
источник
3
Первая фатальная ошибка, упомянутая в вашем примере с включенными строгими типами, неверна. Как упоминалось в документации: «Единственное исключение из этого правила - целое число может быть присвоено функции, ожидающей число с плавающей точкой». Вызов функции не завершился бы ошибкой для int. Хотя это было бы на веревочке.
Пол
63

strict_types влияет на приведение типов.

Использование подсказок типов без них strict_typesможет привести к незначительным ошибкам.

До жестких типов это int $xозначало « $xдолжно иметь значение, приводимое к int». Любое значение, которое может быть приведено intк типу, будет передавать подсказку типа, включая:

  • собственно int ( 242),
  • поплавок ( 10.17),
  • bool ( true),
  • null, или
  • строка с начальными цифрами ( "13 Ghosts").

Устанавливая strict_types=1, вы сообщаете движку, что int $x«$ x должен быть только целым int, принуждение типа не допускается». У вас есть большая уверенность в том, что вы получаете именно то и только то, что было дано, без какой-либо конверсии и потенциальных потерь.

Пример:

<?php
function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Дает потенциально запутанный результат:

Notice: A non well formed numeric value encountered in /Users/bishop/tmp/pmkr-994/junk.php on line 4
100

Я думаю, что большинство разработчиков ожидают, что intподсказка будет означать «только int». Но это не так, это означает «что-то вроде int». Включение strict_types дает ожидаемое и желаемое поведение:

<?php declare(strict_types=1);

function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Урожайность:

Fatal error: Uncaught TypeError: Return value of get_quantity() must be of the type int, string returned in example.php:4

Я думаю, здесь есть два урока, если вы используете подсказки типа:

  • Используйте strict_types=1всегда.
  • Преобразуйте уведомления в исключения, если вы забыли добавить strict_typesпрагму.
епископ
источник
1
На это уже есть хороший ответ, как и почти год назад;)
emix
6
Действительно, я проголосовал за другой ответ @emix. Однако я чувствовал, что вопрос «должен ли я это делать» не был затронут. Я также чувствовал, что более компактный и шокирующий пример побудит людей использовать strict_types.
епископ
1
Я думаю, что этот вопрос кратко отвечает на вопрос: «Стоит ли мне это делать?». часть вопроса ОП. Возвращение к PHP после небольшого перерыва, и это было очень полезно.
Дарра Энрайт,
1

Строгие типы в PHP влияют на типы принуждения.

Устанавливая «strict_types = 1», вы сообщаете движку, что «int $ x» означает «$ x должен быть только соответствующим int, принуждение типа не допускается». У вас есть большая уверенность в том, что вы получаете именно то и только то, что было дано, без какой-либо конверсии или потенциальных потерь.

Все, что вам нужно знать о строгих типах в PHP :)

https://medium.com/@chemaclass/strict-types-in-php-d4166bd25394

Chemaclass
источник