安全的 PHP – 重写的内置函数以抛出异常消息

在 David Négrier 的 Safe PHP 项目中,所有返回的 PHP 函数false都被重写为抛出异常。

自述文件描述了false在异常处理来到 PHP 之前函数返回的问题:

大多数 PHP 核心函数都是在将异常处理添加到该语言之前编写的。因此,大多数 PHP 函数不会抛出异常。相反,它们会在出现错误时返回 false。

自述文件进一步解释了false使用当前语言功能检查代码的内容:

$content = file_get_contents('foobar.json');
if ($content === false) {
    throw new FileLoadingException('Could not load file foobar.json');
}
$foobar = json_decode($content);
if (json_last_error() !== JSON_ERROR_NONE) {
    throw new FileLoadingException('foobar.json does not contain valid JSON: '.json_last_error_msg());
}
对此的 Safe PHP 解决方案如下:

Safe-PHP 重新声明所有核心 PHP 函数。新的 PHP 函数与旧函数完全一样,只是它们在遇到错误时会正确抛出异常。“安全”函数与核心 PHP 函数同名,只是它们位于 Safe 命名空间中。

下面是使用这个包的函数的样子:

use function Safe\file_get_contents;
use function Safe\json_decode;
// This code is both safe and simple!
$content = file_get_contents('foobar.json');
$foobar = json_decode($content);
您可以了解有关此存储库的更多信息并访问GitHub 上的源代码。这个包也有一些自动重构的能力。

注意:Safe PHP 包被声明为实验性的,并且还没有达到 1.0,PHP 8.0:空安全运算符
版本
8.0
类型
新功能
Null-safe 运算符是 PHP 8.0 中的一种新语法,它为 PHP 提供了可选的链接功能。

空安全运算符允许读取属性的值和方法返回值链接,其中空安全运算符在值为 时短路检索null,而不会导致任何错误。

语法类似于属性/方法访问运算符 ( ->),并且遵循可空类型模式,空安全运算符是?->。

$foo?->bar?->baz;
如果左侧的表达式的计算结果为 ,则Null 安全运算符会静默返回nullnull。

class Customer {
    public function getAddress(): ?Address {}
}
class Address {
    public function getCountry(): string {}
}

$country = $customer->getAddress()->getCountry();
在上面的代码片段中,Customer::getAddress()方法返回值可以为空;它可以返回一个null值,或者一个Address类的对象。

该$customer->getAddress()->getCountry()链不是“空安全的”,因为getAddresscan的返回值null,并且 PHP 在尝试调用getCountry()方法时抛出错误:

Fatal error: Uncaught Error: Call to a member function getCountry() on null in ...:...
为了安全地访问地址,有必要null在进一步访问返回值之前检查返回值。

$address = $customer->getAddress();
$country = $address ? $address->getCountry() : null;
$address = $customer->getAddress();
if ($address) {
    $country = $address->getCountry();
}
else {
    $country = null;
}
空安全运算符通过短路属性/方法访问来解决这个问题,null如果运算符的左侧是 ,则立即返回null,而不执行表达式的其余部分。

 $address = $customer->getAddress();
 $country = $address ? $address->getCountry() : null;
 $country = $customer->getAddress()?->getCountry(); 
空?->安全运算符可以帮助减少过多http://www.022cj.com/isset()的三元检查。

在 alpha 3 版本和第一个 beta 版本之间,PHP 8.0 中添加了 Null-safe 运算符,就在 PHP 8.0达到其特性冻结的时候。

只读
空安全运算符是只读的。它不能从中写入/分配值。

class Customer {
    private ?Address $address;

    public function getAddress(): ?Address {
        return $this->address;
    }
}

class Address {
    public string $country;
}

$customer->getAddress()?->country = 'NL';
此代码段尝试写入对象的$country属性Address。空安全运算符不允许这样做。

Fatal error: Can't use nullsafe operator in write context in ... on line ...
链接
可以链接 null 安全运算符,并且整个表达式将从遇到 null 的第一个 null 安全运算符短路。

$customer->getAddress()?->getCoordinates()->getLongitude()->format();
这个调用链是空安全的。null如果任何空安全返回运算符的计算结果为 ,PHP 将停止并立即返回null。

{code-ok} 空安全运算符必须存在于链可以短路的每一步。使用?->运算符不会使整个链成为空安全的。

从左到右计算
空安全运算符是从左到右求值的。最重要的是,它不会优先考虑其他函数调用或其他访问模式,例如数组访问。

<?php

class Customer {
    public function getAddress(): ?Address {}
}

class Address {
    public function setCountry(string $country_code): void {}
}

$customer->getAddress()?->setCountry(GeoIP::getCountry());
如果该Customer::getAddress方法返回一个有效的Address对象,GeoIP::getCountry()将被执行,并传递给Address::setCountry()方法调用。因为 null 安全运算符是从左到右计算的,所以如果方法返回,GetIP::getCountry()则永远不会调用该方法。Customer::getAddress()null

请注意,使用大括号会使大括号内的表达式一起执行,这与 left-to-write 模式相反。

$customer->getAddress()?->setCountry((GeoIP::getAddress()?->getCountry()))
如果Customer::getAddress()返回的值不是null,(GeoIP::getAddress()?->getCountry())链将被执行,返回值将被传递给Address::setCountry()调用。

没有参考资料
空安全运算符不能与引用一起使用。

$country = &$customer->getAddress()?->getCountry();
Fatal error: Cannot take reference of a nullsafe chain in ... on line ...
向后兼容性影响
Null 安全运算符是一种新语法,不能向后移植到旧的 PHP 版本。

运行使用空安全运算符的代码将引发解析错误:

Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR) in ... on line ...

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值