What does strict types do in PHP?

眉间皱痕 提交于 2019-12-25 01:28:14

问题


I've seen this new line in PHP7 but nobody really explains what it means. I've googled it and all they talk about is will you be enabling it or not like a poll type of thing.

declare(strict_types = 1);

What does it do? How does it affect my code? Should I do it? Some explanation would be nice.


回答1:


From Treehouse blog :

With PHP 7 we now have added Scalar types. Specifically: int, float, string, and bool.

By adding scalar type hints and enabling strict requirements, it is hoped that more correct and self-documenting PHP programs can be written. It also gives you more control over your code and can make the code easier to read.

By default, scalar type-declarations are non-strict, which means they will attempt to change the original type to match the type specified by the type-declaration. In other words, if you pass a string that starts with a number into a function that requires a float, it will grab the number from the beginning and remove everything else. Passing a float into a function that requires an int will become int(1).

By default, PHP will cast values of the wrong type into the expected scalar type if possible. For example, a function that is given an integer for a parameter that expects a string will get a variable of type string.

Strict types disabled ( 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)
  */

It is possible to enable strict mode on a per-file basis. In strict mode, only a variable of exact type of the type declaration will be accepted, or a TypeError will be thrown. The only exception to this rule is that an integer may be given to a function expecting a float. Function calls from within internal functions will not be affected by the strict_types declaration.

To enable strict mode, the declare statement is used with the strict_types declaration:

Strict types enabled ( 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

working example :

<?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 affects type coercion.

Using type hints without strict_types may lead to subtle bugs.

Prior to strict types, int $x meant "$x must have a value coercible to an int." Any value that could be coerced to an int would pass the type hint, including:

  • an int proper (242),
  • a float (10.17),
  • a bool (true),
  • null, or
  • a string with leading digits ("13 Ghosts").

By setting strict_types=1, you tell the engine that int $x means "$x must only be an int proper, no type coercion allowed." You have great assurance you're getting exactly and only what was given, without any conversion and potential loss.

Example:

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

Yields a potentially confusing result:

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

Most developers would expect, I think, an int hint to mean "only an int". But it doesn't, it means "anything like an int". Enabling strict_types gives the likely expected and desired behavior:

<?php declare(strict_types=1);

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

Yields:

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

I think there's two lessons here, if you use type hints:

  • Use strict_types=1, always.
  • Convert notices to exceptions, in case you forget to add the strict_types pragma.


来源:https://stackoverflow.com/questions/57804084/how-to-make-functions-with-int-parameters-dont-accept-boolean-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!