PHP严格类型
2015年12月,PHP7引入了标量类型声明,并引入了strict_types标志。该标志可用于强制传递给函数的值的类型。尽管我过去曾经看到过它的实际应用,但是我之前从未真正使用过它,因此我决定对其进行一些研究以了解它的含义。
在某些背景下,类型不是严格在PHP中强制执行的。这意味着不仅可以将变量的类型从一种类型转换为另一种类型,而且还可以根据所使用的上下文将一种类型的变量转换为另一种类型。使用PHP入门的程序员在尝试打印布尔值时会发现这一点,因为在将其打印之前将其转换为整数。这意味着在尝试打印“true”时,PHP会打印出“1”。将值传递给函数时,PHP会自动将值强制转换为另一种类型。
启用标量类型声明后,传递给函数的值必须是声明要接收的函数的类型。默认情况下,标量类型声明在PHP中处于关闭状态。必须通过在每个文件的顶部添加strict_types=1声明来启用它们。
声明看起来像这样。必须将其放置在文件中的任何其他代码之前,并且只会影响放置文件的位置。
让我们通过执行以下功能来了解这一点。该函数接受一个整数值,并将该值作为vardump打印出来。
由于PHP具有松散类型的性质,我们可以将许多不同的值传递给此函数,每个值都会自动转换为整数值。对于这里的每个值,即使在所有情况下传递的原始值都不是整数,但打印的值是1的整数
doThing(1); //打印int(1) doThing("1"); //打印int(1) doThing(TRUE); //打印int(1) doThing(1.0); //打印int(1)现在,如果我们在文件的顶部添加strict_types声明,我们可以尝试再次运行相同的代码。
第一行(发送整数值)可以正常工作,因为该函数需要将整数值传递给它。一旦我们尝试将任何其他类型的值传递给函数,我们就会看到以下错误。由于对该函数的第二个调用实际上是一个字符串,因此会产生以下错误。
PHP Fatal error: Uncaught TypeError: Argument 1 passed to doThing() must be of the type int, string given, called intest.phpon line 10 and defined in test.php:5标量类型声明可防止您将其他类型的变量发送给函数。通常,PHP会将它们强制转换为正确的值,但是启用标量类型声明后,它将引发致命错误。
我们还可以使用标量类型声明来强制执行函数的返回类型。以下代码定义了一个函数,该函数将接受一个整数值并应返回一个整数值。尽管在代码中有一个故意的错误,因为它只会返回浮点值。
运行上面的代码将产生这样的类型错误。
PHP Fatal error: Uncaught TypeError: Return value of doThing() must be of the type int, float returned in test.php:7请注意,我之前提到过,标量类型声明必须放在每个文件的顶部。这意味着,如果在一个启用了标量类型声明的文件中定义该函数,然后从另一个文件中调用该函数,则将不应用标量类型声明设置。
让我们举个例子,将之前定义的函数放入标量类型声明集已设置的文件中。
现在,在第二个文件中,我们包含第一个文件,然后尝试使用非整数值调用函数。
以这种方式运行代码不会产生任何错误。这是因为启动函数调用的文件不包含标量类型声明。仅当第二个文件包含声明时,代码错误。
从根本上说,标量类型声明更多地是为代码的读者提供的,而不是为使用代码的程序员提供的。必须将其添加到所有文件的顶部这一事实会在逐个文件的基础上对其进行强制执行,因此,如果将其添加到第三方库中,则使用该库的代码将无关紧要。
研究了PHP的此功能后,我认为我将开始在代码中使用它来强制传递到函数和从函数传递的类型。另外,由于它仅在文件中起作用,因此对任何上游代码的影响都已定义为最小,因此不会引起任何不必要的问题。
如果您有兴趣,可以在PHPWiki上看到有关标量类型提示的原始RFC。