PHP7类型提示:作为PHP开发者应该永远铭记

PHP7引入了强类型和返回值类型,但仍然存在一些可能导致错误的陷阱。文章讨论了PHP7中的类型转换问题,强调了使用严格类型声明的重要性,以减少潜在的bug和不一致。通过示例代码,作者揭示了PHP7中可能出现的类型错误,并提醒开发者谨慎使用nullable类型,因为它可能导致不易察觉的问题。建议开发者始终在代码中启用严格类型模式,确保数据类型的可控性和代码的一致性。
摘要由CSDN通过智能技术生成

当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 出现一个不好的格式化数字类型值

定义返回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();

结果如下:

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/

很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了迷茫没方向,不知道该从哪儿入手去提升自己。→→管理整理了一些资料,有 腾讯 等一线大厂进阶知识体系 可供参考(相关学习资料以及笔面试题)

覆盖各个技术栈:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货欢迎加入我的官方群点击此处

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值