php php-7.2

¿Qué hacen los tipos estrictos en PHP?



php-7.2 (2)

He visto esta nueva línea en PHP7 pero nadie realmente explica lo que significa. Lo busqué en Google y de lo único que hablan es si lo habilitarás o no como un tipo de encuesta.

declare(strict_types = 1);

¿Qué hace? ¿Cómo afecta mi código? ¿Debería hacerlo? Alguna explicación estaría bien.


Del blog de Treehouse :

Con PHP 7 ahora hemos agregado tipos Scalar. Específicamente: int, float, string y bool.

Al agregar sugerencias de tipo escalar y habilitar requisitos estrictos, se espera que se puedan escribir programas PHP más correctos y autodocumentados. También le da más control sobre su código y puede hacer que el código sea más fácil de leer.

Por defecto, las declaraciones de tipo escalares no son estrictas, lo que significa que intentarán cambiar el tipo original para que coincida con el tipo especificado por la declaración de tipo. En otras palabras, si pasa una cadena que comienza con un número en una función que requiere un flotante, tomará el número desde el principio y eliminará todo lo demás. Pasar un flotante a una función que requiere un int se convertirá en int (1).

Por defecto, PHP lanzará valores del tipo incorrecto en el tipo escalar esperado si es posible. Por ejemplo, una función que recibe un número entero para un parámetro que espera que una cadena obtenga una variable de tipo cadena.

Tipos estrictos deshabilitados ( 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) */

Es posible habilitar el modo estricto por archivo. En modo estricto, solo se aceptará una variable de tipo exacto de la declaración de tipo, o se lanzará un TypeError. La única excepción a esta regla es que se puede dar un número entero a una función que espera un flotante. Las llamadas a funciones desde las funciones internas no se verán afectadas por la declaración estricta_tipos.

Para habilitar el modo estricto, la declaración de declaración se usa con la declaración estricta_tipos:

Tipos estrictos habilitados ( 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

ejemplo de trabajo:

<?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'');


strict_types afecta la coerción de tipo .

Antes de los tipos estrictos, int $x significaba " $x debe tener un valor similar a un int, pero no necesariamente un int propio". Cualquier cosa que pueda ser forzada a un int propiamente dicho pasaría la pista de tipo, incluyendo:

  • un int propio ( 242 ),
  • un flotador ( 10.17 ),
  • un bool ( 1 ),
  • null o
  • una cadena con dígitos iniciales ( 13 Ghosts ).

Ahora, al establecer strict_types=1 , le dice al motor que int debe significar "exactamente y solo un int propio". Nada más. Tiene una gran y gran seguridad de que está obteniendo exactamente y solo lo que se le dio, sin ninguna conversión y pérdida potencial.

Ejemplo:

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

Produce un resultado potencialmente confuso:

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

La mayoría de los desarrolladores esperarían, creo, una pista int que significa "solo un int". Pero no lo hace, significa "algo así como un int". Habilitar tipos estrictos proporciona el comportamiento probable esperado y deseado:

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

Rendimientos:

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

Creo que hay dos lecciones aquí, si usa sugerencias de tipo:

  • Use strict_types=1 , siempre.
  • Convierta avisos en excepciones, en caso de que olvide agregar el pragma strict_types .