PHP 8.3将于2023年11月23日发布;它对只读类、新json_validate()
函数、最近添加的类的补充Randomizer
、堆栈溢出检测等进行了改进。
在这篇文章中,我们将一一介绍所有功能、性能改进、更改和弃用。
只读修改rfc
该 RFC 提出了两项更改,但仅接受了一项:在克隆时能够重新初始化只读属性。这听起来可能是一件大事,但这个 RFC 只解决了一个非常具体(但重要)的边缘情况:覆盖 中的属性值__clone()
,以便允许深度克隆只读属性。
readonly class Post
{
public function __construct(
public DateTime $createdAt,
) {}
public function __clone()
{
$this->createdAt = new DateTime();
// This is allowed,
// even though `createdAt` is a readonly property.
}
}
您可以在此处阅读有关此 RFC 的深入文章和一些旁注。
#类型化类常量rfc
您现在可以输入提示类常量:
class Foo
{
const string BAR = 'baz';
}
##[Override]
属性rfc
新属性用于显示程序员的意图。它基本上是说“我知道这个方法正在重写父方法。如果这种情况发生变化,请告诉我”。#[Override]
这是一个例子:
abstract class Parent
{
public function methodWithDefaultImplementation(): int
{
return 1;
}
}
final class Child extends Parent
{
#[Override]
public function methodWithDefaultImplementation(): int
{
return 2; // The overridden method
}
}
现在,让我们想象一下父方法在某一时刻更改了其方法名称:
abstract class Parent
{
public function methodWithNewImplementation(): int
{
return 1;
}
}
由于该属性,PHP 将能够检测到不再覆盖任何内容,并且会抛出错误。#[Override]
Child::methodWithDefaultImplementation()
您可以在此处阅读有关该属性的更多信息#[Override]
。
#数组中的负索引打破
如果您有一个空数组,请添加一个具有负索引的项目,然后添加另一个项目,第二个项目将始终从 index 开始0
:
$array = [];
$array[-5] = 'a';
$array[] = 'b';
var_export($array);
//array (
// -5 => 'a',
// 0 => 'b',
//)
从 PHP 8.3 开始,下一项将添加到 index 处-4
:
//array (
// -5 => 'a',
// -4 => 'b',
//)
#匿名只读类升级
以前,您无法将匿名类标记为只读。PHP 8.3 中已修复此问题:
$class = new readonly class {
public function __construct(
public string $foo = 'bar',
) {}
};
#新json_validate()函数
rfc
以前,验证字符串是否为有效 JSON 的唯一方法是对其进行解码并检测是否抛出任何错误。json_validate()
如果您只需要知道输入是否是有效的 JSON,则此新函数非常有用,因为与解码字符串相比,它使用的内存更少。
json_validate(string $json, int $depth = 512, int $flags = 0): bool
#Randomizer
补充rfc
PHP 8.2 添加了新的Randomizer类。本次更新带来了一些小补充:
Randomizer::getBytesFromString(string $string, int $length): string
此方法允许您生成具有给定长度的字符串,该字符串由给定字符串中随机选择的字节组成。
Randomizer::getFloat(
float $min,
float $max,
IntervalBoundary $boundary = IntervalBoundary::ClosedOpen
): float
getFloat()
$min
返回和之间的浮点数$max
。您可以通过枚举来定义是否包含$min
以及$max
应该包含在内IntervalBoundary
。Closed
表示包含该值,表示Open
排除该值。
Randomizer::nextFloat(): float {}
最后,nextFloat()
是 的简写,换句话说:它将为您提供 0 到 1 之间的随机浮点数,其中 1 被排除。getFloat(0, 1, IntervalBoundary::ClosedOpen)
#动态类常量获取rfc
PHP 8.3 允许您使用更动态的语法来获取常量:
class Foo
{
const BAR = 'bar';
}
$name = 'BAR';
// Instead of this:
constant(Foo::class . '::' . $name);
// You can now do this:
Foo::{$name};
#更合适的日期/时间异常rfc 打破
在许多情况下,PHP 只会抛出一个Exception
orError
对象;或者在处理日期和时间时出现错误时发出警告或错误。该 RFC 遍历了所有这些边缘情况,并为它们添加了适当的、专用的例外情况。
我们现在有DateMalformedIntervalStringException
、DateInvalidOperationException
、 和 等例外情况DateRangeError
。
一般来说,这些添加不会破坏任何代码,因为这些新添加的异常和错误是泛型Exception
和Error
类的子类。然而,此 RFC 带来了三个小的重大更改:
- now
Epoch doesn't fit in a PHP integer
返回一个 newDateRangeError
而不是 genericValueError
,它不会子类化。这仅是 32 位平台的问题。 Only non-special relative time specifications are supported for subtraction
带有和 的警告成为新的。DateTime::sub()
date_sub()
DateInvalidOperationException
- 现在,当与 OO 接口一起使用时,解析错误/损坏的字符串时创建的
Unknown or bad format (%s) at position %d (%c): %s
和警告将抛出一个新的警告,而不是显示警告并返回 false。String '%s' contains non-relative elements
DateInterval
DateMalformedIntervalStringException
#改进的unserialize()
错误处理rfc
unserialize()
E_WARNING
现在遇到问题时总是会发出 a而不是有时发出E_NOTICE
.
该 RFC 还建议在运行时添加更多异常unserialize()
,但该部分并未被接受。
#range()函数
变更打破
从变更日志:
TypeError
现在,当传递对象、资源或数组作为边界输入时会抛出AValueError
当传递 0 时会抛出更具描述性的$step
ValueError
现在,当使用负数$step
来增加范围时会抛出A- 如果
$step
是一个可以解释为int的float,现在就这样做了 ValueError
如果任何参数是infinity
或,现在会抛出ANAN
- 如果or是空字符串,
E_WARNING
现在会发出An 。该值继续转换为值 0。$start
$end
- 现在,如果或具有多个字节,且仅当它是非数字字符串时,
E_WARNING
才会发出An 。$start
$end
E_WARNING
现在,如果$start
or被转换为整数,则会发出An$end
,因为另一个边界输入是数字。(例如range(5, 'z');
)E_WARNING
现在,当尝试生成一系列字符时,如果 $step 是浮点数,则会发出 An ,除非两个边界输入都是数字字符串(例如,不会range('5', '9', 0.5);
产生警告)range()
现在,如果边界输入之一是字符串数字,则生成字符列表,而不是将另一个输入转换为 int (例如range('5', 'z');
)
#特征和静态属性打破
从变更日志:
使用具有静态属性的特征现在将重新声明从父类继承的静态属性。这将为当前类创建一个单独的静态属性存储。这类似于直接将静态属性添加到没有特征的类中。
#堆栈溢出检测pr
PHP 8.3 添加了两个新的 ini 指令,称为zend.max_allowed_stack_size
和zend.reserved_stack_size
。Error
当使用超过 和zend.max_allowed_stack_size
之间的差异时,接近溢出调用堆栈的程序现在可能会抛出zend.reserved_stack_size
。
此功能的好处是堆栈溢出引起的分段错误将不再导致段错误,从而使调试变得更加容易。
默认值为,zend.max_allowed_stack_size
这0
意味着 PHP 将自动确定一个值。您还可以提供-1
以表明没有限制或特定的字节数。该zend.reserved_stack_size
指令用于确定“缓冲区”,以便 PHP 仍然能够抛出错误而不是实际耗尽内存。这里的值应该是多个字节,但 PHP 将为您确定一个合理的默认值,因此您不一定需要设置它,除非您遇到特定程序的边缘情况。
最后一点,对于纤程,现有fiber.stack_size
指令用作允许的最大堆栈大小。
zend.max_allowed_stack_size=128K
#新mb_str_pad函数
rfc
来自 RFC:
在 PHP 中,各种字符串函数有两种变体:一种用于字节字符串,另一种用于多字节字符串。然而,多字节字符串函数中值得注意的一个缺陷
mbstring
是str_pad()
. 该str_pad()
函数缺乏多字节字符支持,因此在使用使用多字节编码(如 UTF-8)的语言时会出现问题。该 RFC 建议在 PHP 中添加这样一个函数,我们将其称为mb_str_pad()
.
该函数如下所示:
function mb_str_pad(
string $string,
int $length,
string $pad_string = " ",
int $pad_type = STR_PAD_RIGHT,
?string $encoding = null,
): string {}
#魔术方法闭包和命名参数pr
假设您有一个支持魔术方法的类:
class Test {
public function __call($name, $args)
{
var_dump($name, $args);
}
public static function __callStatic($name, $args) {
var_dump($name, $args);
}
}
PHP 8.3 允许您从这些方法创建闭包,然后将命名参数传递给这些闭包。这在以前是不可能的。
$test = new Test();
$closure = $test->magic(...);
$closure(a: 'hello', b: 'world');
#不变的恒定可见性打破
以前,在实现接口时不会检查常量的可见性。PHP 8.3 修复了此错误,但如果您不知道此行为,则可能会导致某些地方的代码损坏。
interface I {
public const FOO = 'foo';
}
class C implements I {
private const FOO = 'foo';
}
#RFC 的小弃用rfc
与每个版本一样,都有一个 RFC 添加了一堆小的弃用内容。请记住,弃用并不是错误,这些通常对于语言的发展是一件好事。这些是已通过的弃用,您可以在 RFC 中阅读有关它们的更多详细信息:
- 不赞成将负数传递
$widths
给mb_strimwidth()
- 弃用并删除常量
NumberFormatter::TYPE_CURRENCY
- 弃用并删除损坏的 PHP 7.1 之前的 Mt19937 实现 (
MT_RAND_PHP
) - 弃用并删除
ldap_connect()
带有 2 个参数的$host
调用$port
- 弃用字符串评估代码断言的剩余部分
#小但显着的变化
并非 PHP 中的每个更改都会通过 RFC 流程。事实上,大多数更改包括维护和错误修复,并且不需要 RFC。所有这些更改都列在升级文档中。我将列出一些最突出的,但如果您想了解最微小的细节,您绝对应该阅读整个列表。
- 使用FFI时,返回类型为
void
now returnnull
而不是 returned 的C 函数FFI\CData:void
posix_getrlimit()
现在采用可选$res
参数来允许获取单个资源限制。gc_status()
有四个新字段:running
、protected
、full
和buffer_size
。class_alias()
现在支持创建内部类的别名。mysqli_poll()
ValueError
现在,当传递 read 或 error 参数时,会引发 a 。array_pad()
现在仅受数组可以拥有的最大元素数的限制。之前,一次最多只能添加 1048576 个元素。- 新的 posix 函数:
posix_sysconf()
、posix_pathconf()
、posix_fpathconf()
和posix_eaccess()
- 现在,在 posix 系统上执行
proc_get_status()
多次将始终返回正确的值。 opcache.consistency_checks
ini 指令已删除- 改进
array_sum()
和array_product()
https://stitcher.io/blog/new-in-php-83