PHP 8.3 是 PHP 语言的重大更新。
它包含许多新功能,例如类常量的显式类型、只读属性的深度克隆以及随机功能的添加。与往常一样,它还包括性能改进、错误修复和常规清理。
立即升级到 PHP 8.3!类型化类常量
interface
I
{
// We may naively assume that the PHP constant is always a string.
const
PHP
=
'PHP 8.2'
;
}
class
Foo
implements
I
{
// But implementing classes may define it as an array.
const
PHP
=
[];
}
interface
I
{
const
string PHP
=
'PHP 8.2'
;
}
class
Foo
implements
I
{
const
string PHP
=
[];
}
// Fatal error: Cannot use array as value for class constant
// Foo::PHP of type string
动态类常量获取
class
Foo
{
const
PHP
=
'PHP 8.2'
;
}
$searchableConstant
=
'PHP'
;
var_dump
(
constant
(
Foo
::class .
"::
{
$searchableConstant
}
"
));
class
Foo
{
const
PHP
=
'PHP 8.3'
;
}
$searchableConstant
=
'PHP'
;
var_dump
(
Foo
::
{
$searchableConstant
}
);
New #[Override] attribute
use
PHPUnit\Framework\TestCase
;
final class
MyTest
extends
TestCase
{
protected
$logFile
;
protected function
setUp
():
void
{
$this
->
logFile
=
fopen
(
'/tmp/logfile'
,
'w'
);
}
protected function
taerDown
():
void
{
fclose
(
$this
->
logFile
);
unlink
(
'/tmp/logfile'
);
}
}
// The log file will never be removed, because the
// method name was mistyped (taerDown vs tearDown).
use
PHPUnit\Framework\TestCase
;
final class
MyTest
extends
TestCase
{
protected
$logFile
;
protected function
setUp
():
void
{
$this
->
logFile
=
fopen
(
'/tmp/logfile'
,
'w'
);
}
#[
\Override
]
protected function
taerDown
():
void
{
fclose
(
$this
->
logFile
);
unlink
(
'/tmp/logfile'
);
}
}
// The log file will never be removed, because the
// method name was mistyped (taerDown vs tearDown).
By adding the #[Override] attribute to a method, PHP will ensure that a method with the same name exists in a parent class or in an implemented interface. Adding the attribute makes it clear that overriding a parent method is intentional and simplifies refactoring, because the removal of an overridden parent method will be detected.
只读属性的深度克隆
class
PHP
{
public
string $version
=
'8.2'
;
}
readonly class
Foo
{
public function
__construct
(
public
PHP $php
) {}
public function
__clone
():
void
{
$this
->
php
= clone
$this
->
php
;
}
}
$instance
= new
Foo
(new
PHP
());
$cloned
= clone
$instance
;
// Fatal error: Cannot modify readonly property Foo::$php
class
PHP
{
public
string $version
=
'8.2'
;
}
readonly class
Foo
{
public function
__construct
(
public
PHP $php
) {}
public function
__clone
():
void
{
$this
->
php
= clone
$this
->
php
;
}
}
$instance
= new
Foo
(new
PHP
());
$cloned
= clone
$instance
;
$cloned
->
php
->
version
=
'8.3'
;
现在可以在神奇的 __clone 方法中修改只读属性一次,以启用只读属性的深度克隆。
新增 json_validate() 函数
function
json_validate
(
string $string
):
bool
{
json_decode
(
$string
);
return
json_last_error
() ===
JSON_ERROR_NONE
;
}
var_dump
(
json_validate
(
'{ "test": { "foo": "bar" }
}'
));
// true
var_dump
(
json_validate
(
'{ "test": { "foo": "bar" }
}'
));
// true
json_validate() 允许检查字符串在语法上是否是有效的 JSON,同时比 json_decode() 更高效。
新增 Randomizer::getBytesFromString() 方法
// This function needs to be manually implemented.
function
getBytesFromString
(
string $string
,
int
$length
) {
$stringLength
=
strlen
(
$string
);
$result
=
''
;
for (
$i
=
0
;
$i
<
$length
;
$i
++) {
// random_int is not seedable for testing, but secure.
$result
.=
$string
[
random_int
(
0
,
$stringLength
-
1
)];
}
return
$result
;
}
$randomDomain
=
sprintf
(
"%s.example.com"
,
getBytesFromString
(
'abcdefghijklmnopqrstuvwxyz0123456789'
,
16
,
),
);
echo
$randomDomain
;
// A \Random\Engine may be passed for seeding,
// the default is the secure engine.
$randomizer
= new
\Random\Randomizer
();
$randomDomain
=
sprintf
(
"%s.example.com"
,
$randomizer
->
getBytesFromString
(
'abcdefghijklmnopqrstuvwxyz0123456789'
,
16
,
),
);
echo
$randomDomain
;
PHP 8.2 中添加的随机扩展通过一种新方法进行了扩展,以生成仅由特定字节组成的随机字符串。该方法允许开发人员轻松生成随机标识符,例如域名和任意长度的数字字符串。
新增 Randomizer::getFloat() 和 Randomizer::nextFloat() 方法
// Returns a random float between $min and $max, both including.
function
getFloat
(
float $min
,
float $max
) {
// This algorithm is biased for specific inputs and may
// return values outside the given range. This is impossible
// to work around in userland.
$offset
=
random_int
(
0
,
PHP_INT_MAX
) /
PHP_INT_MAX
;
return
$offset
* (
$max
-
$min
) +
$min
;
}
$temperature
=
getFloat
(-
89.2
,
56.7
);
$chanceForTrue
=
0.1
;
// getFloat(0, 1) might return the upper bound, i.e. 1,
// introducing a small bias.
$myBoolean
=
getFloat
(
0
,
1
) <
$chanceForTrue
;
$randomizer
= new
\Random\Randomizer
();
$temperature
=
$randomizer
->
getFloat
(
-89.2
,
56.7
,
\Random\IntervalBoundary
::
ClosedClosed
,
);
$chanceForTrue
=
0.1
;
// Randomizer::nextFloat() is equivalent to
// Randomizer::getFloat(0, 1, \Random\IntervalBoundary::ClosedOpen).
// The upper bound, i.e. 1, will not be returned.
$myBoolean
=
$randomizer
->
nextFloat
() <
$chanceForTrue
;
由于浮点数的精度有限和隐式舍入,生成位于特定区间内的无偏浮点数并非易事,并且常用的用户态解决方案可能会生成有偏差的结果或超出请求范围的数字。
随机发生器还通过两种方法进行了扩展,以无偏的方式生成随机浮点数。 Randomizer::getFloat() 方法使用在 Drawing Random Floating-Point Numbers from an Interval 中发布的 γ 部分算法。 Frédéric Goualard,ACM 翻译。模型。计算。同时,32:3,2022 年。
命令行 linter 支持多个文件
php -l foo.php bar.php
No syntax errors detected in foo.php
php -l foo.php bar.php
No syntax errors detected in foo.php
No syntax errors detected in bar.php
命令行 linter 现在接受文件名的可变输入以进行 lint
新增类、接口和函数
- 新增 DOMElement::getAttributeNames()、DOMElement::insertAdjacentElement()、DOMElement::insertAdjacentText()、DOMElement::toggleAttribute()、DOMNode::contains()、DOMNode::getRootNode()、DOMNode::isEqualNode()、 DOMNameSpaceNode::contains() 和 DOMParentNode::replaceChildren() 方法。
- 新增 IntlCalendar::setDate()、IntlCalendar::setDateTime()、IntlGregorianCalendar::createFromDate() 和 IntlGregorianCalendar::createFromDateTime() 方法。
- 新增 ldap_connect_wallet() 和 ldap_exop_sync() 函数。
- 新增 mb_str_pad() 函数。
- 新增 posix_sysconf()、posix_pathconf()、posix_fpathconf() 和 posix_eaccess() 函数。
- 新增 ReflectionMethod::createFromMethodName() 方法。
- 新增 socket_atmark() 函数。
- 新增 str_increment()、str_decrement() 和stream_context_set_options() 函数。
- 新增 ZipArchive::getArchiveFlag() 方法。
- Support for generation EC keys with custom EC parameters in OpenSSL extension.
- 新增 INI 设置 zend.max_allowed_stack_size 来设置允许的最大堆栈大小。
- php.ini 现在支持后备/默认值语法。
- 匿名类现在可以是只读的。
弃用和向后兼容性中断
- 更合适的日期/时间例外。
- 现在,将负索引 n 分配给空数组将确保下一个索引是 n 1 而不是 0。
- range() 函数的更改。
- Changes in re-declaration of static properties in traits.
- U_MULTIPLE_DECIMAL_SEPERATORS 常量已被弃用,取而代之的是 U_MULTIPLE_DECIMAL_SEPARATORS。
- MT_RAND_PHP Mt19937 变体已弃用。
- ReflectionClass::getStaticProperties() 不再可为空。
- INI 设置assert.active、assert.bail、assert.callback、assert.exception 和assert.warning 已被弃用。
- 不推荐调用不带参数的 get_class() 和 get_parent_class()。
- SQLite3:默认错误模式设置为异常。
PHP 手册中提供了迁移指南。请参阅它以获取新功能和向后不兼容更改的详细列表。
如果需要下载以前的版本,可以查看 更多变更日志