PHP中的严格类型有什么作用?

suf*_*uko 92 php weak-typing strong-typing php-7.2

我在PHP7中看到了这个新系列,但没有人真正解释它的含义.我用谷歌搜索了它,所有他们谈论的是你是否会启用它或者不喜欢民意调查类型.

declare(strict_types = 1);

它有什么作用?它如何影响我的代码?我应该这样做吗?一些解释会很好.

sai*_*aif 105

来自树屋博客:

使用PHP 7,我们现在添加了Scalar类型.具体来说:int,float,string和bool.

通过添加标量类型提示并启用严格要求,希望可以编写更正确且自我记录的PHP程序.它还使您可以更好地控制代码,并使代码更易于阅读.

默认情况下,标量类型声明是非严格的,这意味着它们将尝试更改原始类型以匹配type-declaration指定的类型.换句话说,如果将以数字开头的字符串传递给需要浮点数的函数,它将从头开始获取数字并删除其他所有数字.将float传递给需要int的函数将成为int(1).

默认情况下,如果可能,PHP会将错误类型的值转换为预期的标量类型.例如,为需要字符串的参数赋予整数的函数将获得string类型的变量.

禁用严格类型:

<?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)
  */
Run Code Online (Sandbox Code Playgroud)

可以基于每个文件启用严格模式.在严格模式下,只接受类型声明的确切类型的变量,否则将抛出TypeError.此规则的唯一例外是可以为期望浮点的函数赋予整数.内部函数内的函数调用不受strict_types声明的影响.

要启用严格模式,declare语句与strict_types声明一起使用:

已启用严格类型:

<?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
Run Code Online (Sandbox Code Playgroud)

工作实例:

<?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');
Run Code Online (Sandbox Code Playgroud)

  • 在启用严格类型的示例中提到的第一个致命错误是错误的。如文档中所述:“此规则的唯一例外是可以将整数赋给需要浮点数的函数。” 函数调用不会在int上失败。它会在字符串上。 (2认同)

bis*_*hop 31

strict_types影响类型强制.

在严格类型之前,int $x意味着" $x必须具有类似于 int 的值,但不一定是int本身." 任何可能被强制转换为int正确的东西都会传递类型提示,包括:

  • 一个int本(242),
  • 一个float(10.17),
  • 一个布尔(1),
  • null, 要么
  • 带有前导数字的字符串(13 Ghosts).

现在,通过设置strict_types=1,您告诉引擎int必须表示"确切且仅适用于int".没有其他的.你有一个伟大而伟大的保证,你得到的只是给出的,没有任何转换和潜在的损失.

例:

<?php
function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;
Run Code Online (Sandbox Code Playgroud)

产生了一个可能令人困惑的结果:

Notice: A non well formed numeric value encountered in /Users/bishop/tmp/pmkr-994/junk.php on line 4
100
Run Code Online (Sandbox Code Playgroud)

我认为,大多数开发人员都希望int提示"只有一个int".但它没有,它意味着"像int一样".启用严格类型可以提供可能的预期和期望的行为:

<?php declare(strict_types=1);

function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;
Run Code Online (Sandbox Code Playgroud)

产量:

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

如果您使用类型提示,我认为这里有两个课程:

  • strict_types=1始终使用.
  • 如果您忘记添加strict_typespragma ,请将通知转换为异常.

  • 我认为这个问题简洁地解决了“我应该这样做吗?” OP问题的一部分。中断一段时间后返回 PHP,这非常有帮助。 (5认同)
  • 大约一年前,这已经得到了很好的回答;) (2认同)
  • 确实,我投票赞成其他答案@emix。但是,我觉得“我应该做”这个问题没有被提及。我也觉得一个更紧凑和令人震惊的例子会鼓励人们使用“ strict_types”。 (2认同)