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


147

我已经在PHP 7中看到以下新行,但是没有人真正解释它的含义。我已经用谷歌搜索了,他们谈论的只是您是否启用它,而不是像民意调查这类的东西。

declare(strict_types = 1);

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

一些解释会很好。



5
。也看看这个php.net/manual/en/…for strict_types指令
scaisEdge

Answers:


153

树屋博客

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

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

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

默认情况下,PHP会尽可能将错误类型的值转换为预期的标量类型。例如,为期望字符串的参数提供整数的函数将获得字符串类型的变量。

严格类型禁用(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声明的影响。

要启用严格模式,将define语句与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 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');

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

63

strict_types 影响类型强制。

如果不使用类型提示,则strict_types可能导致细微的错误。

在使用严格类型之前,其int $x含义是“ $x必须具有对int 强制的值”。可以强制转换为的任何值都int将通过类型提示,包括:

  • 一个int专有(242),
  • 浮点数(10.17),
  • 布尔(true),
  • null, 要么
  • 带有前导数字("13 Ghosts")的字符串。

通过设置strict_types=1,您告诉引擎int $x意味着“ $ x只能是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”。但这不是,它的意思是“像整数一样的东西”。启用strict_types会给出可能的预期和期望的行为:

<?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实用程序。

1
差不多一年前,这已经得到了很好的回答;)
emix

6
确实,我投票赞成其他答案@emix。但是,我觉得“我应该做”这个问题没有被提及。我还觉得一个更紧凑,更令人震惊的例子会鼓励人们使用strict_types
主教

1
我认为这个问题简洁地回答了“我应该这样做吗?” OP问题的一部分。稍作中断后返回PHP,这非常有帮助。
Darragh Enright
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.