在 PHP 7 中全局启用 'strict_types'。

69
我目前正在将我的网站从PHP5迁移到PHP7,并且开始使用新增的严格类型功能。然而,这要求我在所有文件中都以以下行开始:
<?php declare(strict_types=1);

// All other code here
// ...

我在想,有没有办法通过类似于php.ini或者Apache配置文件的方式全局启用strict_types,这样我就不必每次都写这一行代码了。如果可以的话,应该如何启用呢?

3
不,这是不可能的。 - u_mulder
5
您可以使用sedawk或其他您选择的工具全局启用严格类型,将所有的 <?php 替换为 <?php declare(strict_types=1); 即可。请注意,此操作不应更改原始代码的含义。 - NikiC
@NikiC 我相信在任何IDE中进行简单的查找替换都可以达到同样的效果,我只是想知道是否可能作为标准功能在运行时完成此操作,因为我没有找到相关信息。 - Paradoxis
1
你可以始终设置一个git钩子,检查所有PHP文件的第一行是否为 <?php declare(strict_types=1);。这样可以在不强制库的情况下,强制执行项目中的规则。 - Cruncher
PHP CS Fixer 中的 declare_strict_types 选项可以强制所有文件使用严格类型。如果您有多个开放标签,它比字符串替换更好。它可以集成并在 IDE 中自动运行。 - Mark Fisher
3个回答

82
这是故意不可能的,因为在对标量类型提示进行了非常长时间的讨论后,采用的实现方式是这样的:https://wiki.php.net/rfc/scalar_type_hints_v5 它引入了两种标量类型参数的模式,两种模式都保证函数在接收参数时得到其在签名中所需的类型。然而,它提供了两种调用代码实现这一目标的模式:
- 在模式0中,它会自动验证和转换某些标量类型(例如,将int参数将'123'转换为123,但对于'hello'则报错) - 在模式1中,它要求调用者在调用之前进行验证和转换,并拒绝任何不正确类型的参数(例如,对于int参数,'123''hello'都会被拒绝)
选择模式是基于文件和函数的调用者的,因为:
  • 设置需要影响内置函数和用户定义的函数
  • 所有调用函数的代码都需要检查或更新,以在模式1下正确工作,但大多数旧代码在模式0下仍然可以正常运行
  • 通过全局设置,您只能使用已经与两种模式进行过测试的库,或者与您偏好的相同模式的库
  • 没有声明其首选模式的文件需要继续以类似于PHP 5.x的方式工作,以允许现有代码运行;这只有在默认为模式0时才可能实现

从一个编写可重用库的人的角度来看:

无论设置如何,您的函数都保证接收所请求的参数类型。 如果您希望在调用具有错误类型的函数时收到错误信息,可以使用模式1,而无需强制其他应用程序和库处于相同的设置。 如果您希望拥有模式0的自动检查和转换功能,也可以做到这一点,同时与以模式1运行的其他库和应用程序进行交互。 旧的库在PHP 7.0之前编写(或者需要在其发布时支持两种模式)的库将继续以类似于内置函数的现有行为方式工作,因为默认的模式0与现有行为相似。 因此,您需要告诉PHP哪些文件已经被编写为使用严格类型模式,哪些没有;而要做到这一点,可以使用declare语句。

1
@sorpigal,我从未说过它不可能实现;我说过在长时间的(顺便说一下,经常是激烈的)辩论之后,决定让调用者控制是最好的想法。如果你要修补PHP,你可以在某人使用不正确的类型时将其修补为halt-and-catch-fire,但那不是同样的功能。 - IMSoP
@IMSoP 谢谢,解释得很好,但是它让我确信应该有这样的选项,尽管我担心库的兼容性可能会成为这个理想的崩溃点。这确实是一个非常有效的论点 (dltdcmmnt2rdcspc) - jave.web
1
@jave.web 或许如果20年前PHP能像现在的strict_types=1一样工作,并且有更好的类型转换行为,那就太理想了,这样(int)'hello'就会报错而不是返回0。但是,无论是现在还是7.0发布时,添加全局设置都解决不了什么问题,反而会造成很多损害。 - IMSoP
@IMSoP 我的意思是将ideal作为名词 - 这就是为什么我称之为ideal(像意识形态一样)。否则,我同意它支持我的说法。(是的,理想可以带来不良后果) - jave.web
我理解对于支持旧库的担忧,但他们可以将其默认为不使用严格类型,这样编写没有此类问题的内容的人就不会受到阻碍。 - C Miller
显示剩余3条评论

18
PHPStorm有一个检查功能可以协助您完成此操作: 输入图像说明

10
虽然没有严格回答问题,但仍然很有帮助,谢谢。(: - Scolopendre
5
我看到你做的那个双关语的类型了。 - James

7
基本上不需要。如果你只需要使用已经使用严格模式的库,那么你就会导致一些不必要的软件包分离。此外,请注意,PHP中的严格/弱类型选项只是一个额外的选项。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接