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

2022-08-30 06:12:03

我在 PHP 7 中看到了下面的新行,但没有人真正解释它的含义。我已经用谷歌搜索了它,他们谈论的只是你会启用它还是不喜欢民意调查类型的东西。

declare(strict_types = 1);

它有什么作用?它如何影响我的代码?我应该这样做吗?

一些解释会很好。


答案 1

来自树屋博客

在 PHP 7 中,我们添加了标量类型。具体来说:int、float、string 和 bool。

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

默认情况下,标量类型声明是非严格声明,这意味着它们将尝试更改原始类型以匹配类型声明指定的类型。换句话说,如果将以数字开头的字符串传递到需要浮点数的函数中,它将从头开始获取该数字并删除其他所有内容。将浮点数传递到需要 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。此规则的唯一例外是,可以将整数赋给期望浮点数的函数。从内部函数内部调用函数不会受到strict_types声明的影响。

若要启用严格模式,声明语句与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

工作实例:

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

答案 2

strict_types会影响类型强制。

使用不带strict_types的类型提示可能会导致细微的错误。

在严格类型之前,意味着“必须具有可强制到int的值”。任何可以强制为 的值都将传递类型提示,包括:int $x$xint

  • 一个整型正确 (),242
  • 浮子 (),10.17
  • 一个布尔 (),true
  • null
  • 带有前导数字 () 的字符串。"13 Ghosts"

通过设置 ,您告诉引擎这意味着“$x只能是 int 本身,不允许类型强制。你有很大的保证,你得到的是准确且只得到的东西,没有任何转换和潜在的损失。strict_types=1int $x

例:

<?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一样的东西”。启用strict_types将给出可能的预期和期望行为: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

推荐