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

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

declare(strict_types = 1);

Что оно делает? Как это влияет на мой код? Я должен это сделать? Некоторые объяснения были бы приятными.

Ответ 1

Из блога Treehouse:

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

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

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

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

Строгие типы отключены (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. Единственное исключение из этого правила состоит в том, что целое число может быть дано функции, ожидающей float. Вызовы функций из внутренних функций не будут затронуты объявлением strict_types.

Чтобы включить строгий режим, выражение объявления используется с объявлением 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 on 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');

Ответ 2

strict_types влияет на приведение типов и, если вы используете подсказки типов без strict_types = 1, вы можете быть удивлены.

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

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

Теперь, установив strict_types=1, вы сообщаете движку, что int должен означать "точно и только int 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". Включение строгих типов дает вероятное ожидаемое и желаемое поведение:

<?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.