PHP7类型提示:作为PHP开发者应该永远铭记
推荐教程:《PHP7》
本文翻译自http://web-techno.net/typing-with-php-7-what-you-shouldnt-do/,英语好的请移步原文。
当PHP7出现了强类型,我看到了光明。我终于有信心不会再因为PHP弱类型看见bug或者不一致的情况。
我记着读过一些代码,对其中的变量该是的类型没什么想法。这个方法我该使用int类型作为返回值?boolen类型?这样将会产生一些隐藏的bug或者不可预见的行为?
严格类型很有用,返回值类型提示也很有用。你很了解你正处理的数据是什么。你再也不用靠猜了。
但是,PHP7并不是我这篇文章努力的结束。你仍可以写易混淆的代码,即使PHP7努力去修复这个问题。你需要遵守一些规则来使你的代码保持规范。
我会使用PHP7.1.1-dev的命令行模式运行本文的每个例子。
PHP类型声明
PHP7引入了两个合适类型:标量类型和返回值类型。我在这不会解释它们的不同以及如何去使用它们。PHP意见征求稿会比我做得更好:
*https://wiki.php.net/rfc/scalar_type_hints_v5
*https://wiki.php.net/rfc/return_types
PHP7有强类型...还是很奇怪?
直截了当些:PHP7编程可能会有一些不可预期的结果。
对此怀疑?以下一些例子:
function mySuperFunction(): int{ return "hello world"; } mySuperFunction();
这段代码没问题。类型声明指出这个方法应该返回int类型。然而,它返回字符串类型。毋庸置疑,PHP会抛出了一个错误:
Fatal error: Uncaught TypeError: Return value of mySuperFunction() must be of the type integer, string returned. 致命错误:未捕捉的类型错误:mySuper函数返回类型必须是int类型,返回了字符串。
让我们看另一个例子:
function mySuperFunction():int{ return "hello world1"; } mySuperFunction();
和上边相同的结果:类型错误。好!返回类型有什么问题吗?我没骗到你吧?
function mySuperFunction():int{ return "1hello world"; } mySuperFunction();
这不是应该抛出异常吗?我们很明确地定义了返回类型为int,但返回的却是一个字符串。
翻译作者补充:PHP7.2.4会抛出注意型错误:
Notice: A non well formed numeric value encountered 出现一个不好的格式化数字类型值
错。函数返回1。
function mySuperFunction():int{ return 1.1456415; } mySuperFunction();
定义返回int类型,很明显,实际返回的是float类型。但是这段代码不抛出异常。
它返回1.
还不服气?
function mySuperFunction():bool{ return "1hello world"; } mySuperFunction();
PHP会把'1hello world'视作是布尔类型并返回1。
function mySuperFunction():bool{ return "abcde"; } mySuperFunction();
在奇怪的的PHP世界中,'abcde'是布尔类型。的确,这个方法会返回true!
如你所见,这些编码规则仍旧把你搞得晕头转向。简而言之,即使代码交代清楚也不一定是真的!
PHP严格类型
PHP习惯弱类型。
我不愿意。
事实上PHP会在运行时默默地把字符串类型转换成布尔类型,转换成int类型。就把你的代码搞混了!本该简单明了的东西搞乱了。
让我们明确下。我们是开发者。因此我们应该在代码中控制数据的类型。
如果我们不这样,我们将打开bug之门,在开发者间传播怪行为和误解。代码将会改变。bug将会出现,老板将会解雇了你,妻子将会对你失望,你将会坠入深渊。在自责中难过、孤独。
还有补救的机会!所有事情都可能。PHP有解决方法!
注意严格类型模式:
declare(strict_types=1);function mySuperFunction(): bool{ return 'abcde'; }echo mySuperFunction();
运行这段代码,你将会得到一个致命的错误:
Fatal error: Uncaught TypeError: Return value of mySuperFunction() must be of the type boolean, string returned!
未捕获的类型错误:mySuperFunction()返回值必须是布尔类型,返回了字符串!
我十分高兴看到这个错误在屏幕弹出。通常遇到错误都不是很爽,但是这次没什么。当然是字符串类型而不是布尔类型!
我的建议是:把这个严格类型的声明放到的每一段代码中。任何地方!为你的IDE创建一个代码片段。每次创建一个PHP文件时,你应该把严格类型的声明放到顶部。
不幸的是你不能全局地设置严格模式。你需要在每个PHP文件中执行。理由很简单:你应用中的任何包或者其他类型的资源,即使不需要执行强类型模式。
我知道有人会不认同。我知道一些人正准备毁掉代码一致性,然后单纯地为了可能的「灵活性」。
我知道争论:「一种观点认为布尔类型需要被展示为字符串类型是很容易的」。
我会回复他们:修复你的结构和/或你的实现。如果代码是弱类型,就会有一些问题。如果你确实需要,请修复真实存在的问题,不用再徘徊于把布尔值作为一个字符串或者int类型。
你是开发者。你不是黑客。你要解决问题,而不是与问题为伍。
五个字概括:强类型骄傲!PHP7是强类型类型语言了!
PHP7.1中Nullable类型 请小心nullable类型的笑里藏刀!它是猛兽!
nullabla类型详见PHP意见征求稿
你怎么会用错?
declare(strict_types=1);class User{ //Value object}class UserRepository{ private $database; public function construct(Database $database){ $this->database = $database; } public function getUserById(int $id):?User { //If user is not in the database, return null $user = $this->database->fetchUser($id); return $user; } }class EmailSender{ public function sendEmailToUser(int $userId) { $userRepository = new UserRepository(new Database()); $user = $userRepository->getUserById($userId); //Can send email to... null! $this->sendEmail($user); } } $emailSender = new EmailSender(); $emailSender->sendEmailToUser(12345);
这段代码将会崩溃,因为我们试图获取数据库中不存在的User模型。我们怎么能给null发邮件?
很明显你应该用如下方法修正:
...class EmailSender{ public function sendEmailToUser($userId) { $userRepository = new UserRepository(new Database()); $user = $userRepository->getUserById($userId); if ($user !== null) { $this->sendEmail($user); } } }
但是这个方法有两个问题:
对nullable的处理将导致判断是否为null的判断到处都是(if ($methodReturn !== null))。无用且聒噪。
如果用户不存在以上代码将会静静地失败。「为什么用户没收到邮件?」将会是你的噩梦。你需要明白:
用户模型不存在(可能是一个错误的用户id被传入了getUserByid())
用户模型为null,可能因为nullable类型
加上null的条件判断,导致应用什么都没做
这是另一种方式:
...class UserRepository{ private $database; public function construct($database){ $this->database = $database; } public function getUserById($id):User { $user = $this->database->fetchUser($id); //If user is not in the database, an error will be thrown! return $user; } } ...
在这个例子中没必要使用nullalble类型。代码将会抛出一个异常。如果User模型不存在,应用的执行将会终止。
那时你仅需要去处理这个错误。简单、清晰、高效,毋庸置疑。
PHP中nullable类型和接口
nullable类型有一些其他的意外。
declare(strict_types=1);interface MySuperInterface{ public function superFunction():?int; }class SuperClass implements mySuperInterface{ public function superFunction():int { return 42; } } $superClass = new SuperClass();echo $superClass->superFunction();
Super类实现了接口MySubper,但不会实现接口约定。接口要求返回nullable的类型,实际将返回int类型。
然而,这段代码在PHP7.1中不会抛出错误。
等等。。。我们需要如接口中表示的那样无论如何都要返回null?
让我们尝试一下:
declare(strict_types=1);interface MySuperInterface{ public function superFunction():?int; }class SuperClass implements mySuperInterface{ public function superFunction():int { return null; } } $superClass = new SuperClass();echo $superClass->superFunction();
结果如下:
Fatal error: Uncaught TypeError: Return value of SuperClass::superFunction() must be of the type integer, null returned 致命错误:未捕获的类型错误:Super类的super方法的返回值必须得是int类型,返回了null
现在我应该理解了在某场景下很有用,比如不能在数据库中存null值时。
我强烈建议你谨慎使用。我很少在代码中使用这个类型,因为我通常有更好的解决办法。
我更喜欢在大多场景下使用null对象代替null。为什么?简而言之,因为我讨厌在任何时候检测变量是否为null!
长话短说:一定要小心
我喜欢PHP。尤其当它引入了强类型。可能还不完美,但是将会越来越好。
不过当你在PHP中操作类型时,一定要多加小心。我还是要强调:
需要使用严格类型。
需要控制应用中数据。
如果仍使用弱类型,将会是个问题。因此:修复它!
不应该猜测变量的类型到底是什么。
尽可能避免使用nullable类型
为了每个使用我们的代码的开发人员,我们需要保持一致性。对我来说,意味着很专业。
很明显在留言中阅读你们的建议使我很开心。
参考:
http://web-techno.net/typing-with-php-7-what-you-shouldnt-do/
以上是PHP7类型提示:作为PHP开发者应该永远铭记的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

php7.0安装mongo扩展的方法:1、创建mongodb用户组和用户;2、下载mongodb源码包,并将源码包放到“/usr/local/src/”目录下;3、进入“src/”目录;4、解压源码包;5、创建mongodb文件目录;6、将文件复制到“mongodb/”目录;7、创建mongodb配置文件并修改配置即可。

在php5中,我们可以使用fsockopen()函数来检测TCP端口。这个函数可以用来打开一个网络连接和进行一些网络通信。但是在php7中,fsockopen()函数可能会遇到一些问题,例如无法打开端口、无法连接到服务器等。为了解决这个问题,我们可以使用socket_create()函数和socket_connect()函数来检测TCP端口。

解决 PHP 7.0 中插件未显示已安装问题的方法:检查插件配置并启用插件。重新启动 PHP 以应用配置更改。检查插件文件权限,确保其正确。安装丢失的依赖项,以确保插件正常运行。如果其他步骤均失败,则重建 PHP。其他可能原因包括插件版本不兼容、加载错误版本或 PHP 配置问题。

PHP服务器环境常见的解决方法包括:确保已安装正确的PHP版本和已复制相关文件到模块目录。临时或永久禁用SELinux。检查并配置PHP.ini,确保已添加必要的扩展和进行正确设置。启动或重启PHP-FPM服务。检查DNS设置是否存在解析问题。

php7.0安装部署的方法:1、到PHP官网下载与本机系统对应的安装版本;2、将下载的zip文件解压到指定目录;3、打开命令行窗口,在“E:\php7”目录下运行“php -v”命令即可。

如何在系统重启后自动设置unixsocket的权限每次系统重启后,我们都需要执行以下命令来修改unixsocket的权限:sudo...

在Docker环境中使用PECL安装扩展时报错的原因及解决方法在使用Docker环境时,我们常常会遇到一些令人头疼的问�...

PHP8相较于PHP7在性能、新特性和语法改进、类型系统、错误处理和扩展等方面都有一些优势和改进。然而,选择使用哪个版本要根据具体的需求和项目情况来决定。详细介绍:1、性能提升,PHP8引入了Just-in-Time(JIT)编译器,可以提高代码的执行速度;2、新特性和语法改进,PHP8支持命名参数和可选参数的声明,使得函数调用更加灵活;引入了匿名类、属性的类型声明等等。
