PHP 中的严格类型有啥作用?

Posted

技术标签:

【中文标题】PHP 中的严格类型有啥作用?【英文标题】:What do strict types do in PHP?PHP 中的严格类型有什么作用? 【发布时间】:2018-07-21 06:35:57 【问题描述】:

我在 php 7 中看到了以下新行,但没有人真正解释它的含义。我用谷歌搜索了它,他们谈论的只是你会启用它还是不喜欢投票类型的东西。

declare(strict_types = 1);

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

解释一下就好了。

【问题讨论】:

php.net/declare .也看看这个php.net/manual/en/… for strict_types 指令 【参考方案1】:

来自Treehouse blog:

在 PHP 7 中,我们现在添加了标量类型。具体来说:int、float、 字符串和布尔值。

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

默认情况下,标量类型声明是非严格的,这意味着它们 将尝试更改原始类型以匹配指定的类型 通过类型声明。换句话说,如果你传递一个字符串 从一个数字开始到一个需要浮点数的函数中,它将 从头开始抓取号码并删除其他所有内容。通过 将浮点数放入需要 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 声明的影响。

要启用严格模式,请使用 declare 语句和 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');

【讨论】:

【参考方案2】:

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”。但它不是,它的意思是“任何像 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 pragma。

【讨论】:

这已经得到了很好的回答,就像一年前一样;) 确实,我对另一个答案@emix 投了赞成票。然而,我觉得“我应该这样做”的问题没有被触及。我还觉得一个更紧凑、更令人震惊的例子会鼓励人们使用strict_types 我认为这个问题简洁地解决了“我应该这样做吗?” OP问题的一部分。暂停一段时间后返回 PHP,这非常有帮助。

以上是关于PHP 中的严格类型有啥作用?的主要内容,如果未能解决你的问题,请参考以下文章

未装箱类型和严格性之间有啥关系?

PHP7 中的标量和严格类型是性能增强功能吗?

PHP7新特性

标量类型与返回值类型声明

PHP7 的新增性能

西门子PLC中的DB块,如何使用有啥作用?数据类型有啥,可以在程序中发挥啥作用呢?新人无法理