PHP 8.3
已发布!
PHP 8.3 是 PHP 语言的主版本更新。它包含了许多新功能,
它包含了许多新功能,例如:类常量显式类型、只读属性深拷贝,以及对随机性功能的补充。一如既往,它还包括性能改进、错误修复和常规清理等。
类型化类常量 RFC
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 = []; }
PHP 8.3
interface I { const string PHP = 'PHP 8.3'; }
class
Foo implements I { const string PHP = []; }// Fatal error: Cannot use array as value for class constant // Foo::PHP of type string
动态获取类常量 RFC
PHP < 8.3
class Foo { const PHP = 'PHP 8.2'; }$searchableConstant = 'PHP';var_dump(constant(Foo::class . "::{$searchableConstant}"));
PHP 8.3
class Foo { const PHP = 'PHP 8.3'; }$searchableConstant = 'PHP';var_dump(Foo::{$searchableConstant});
新增 #[\Override]
属性 RFC
PHP < 8.3
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).
PHP 8.3
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'); } }// Fatal error: MyTest::taerDown() has #[\Override] attribute, // but no matching parent method exists
通过给方法添加 #[\Override]
属性,PHP 将确保在父类或实现的接口中存在同名的方法。添加该属性表示明确说明覆盖父方法是有意为之,并且简化了重构过程,因为删除被覆盖的父方法将被检测出来。
只读属性深拷贝 RFC
PHP < 8.3
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
PHP 8.3
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';
readonly
属性现在可以在魔术方法 __clone
中被修改一次,以此实现只读属性的深拷贝
新增 json_validate()
函数 RFC 文档
PHP < 8.3
function json_validate(string $string): bool { json_decode($string);
return
json_last_error() === JSON_ERROR_NONE; }var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true
PHP 8.3
var_dump(json_validate('{ "test": { "foo": "bar" } }')); // true
json_validate()
可以检查一个字符串是否为语法正确的 JSON,比 json_decode()
更有效。
新增 Randomizer::getBytesFromString()
方法 RFC 文档
PHP < 8.3
// 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;
PHP 8.3
// 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 中新增的 Random 扩展 通过一个新方法生成由特定字节组成的随机字符串。这种方法可以使开发者更轻松的生成随机的标识符(如域名),以及任意长度的数字字符串。
新增 Randomizer::getFloat()
和 Randomizer::nextFloat()
方法 RFC 文档
PHP < 8.3
// 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;
PHP 8.3
$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 扩展了两种方法,用于随机生成无偏差的浮点数。Randomizer::getFloat()
方法使用的是 γ-section 算法,该算法发表于 Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022.
命令行 linter 支持多个文件 PR 文档
PHP < 8.3
php -l foo.php bar.php No syntax errors detected in foo.php
PHP 8.3
php -l foo.php bar.php No syntax errors detected in foo.php No syntax errors detected in bar.php
命令行 linter 现在接受文件名的可变输入以进行 lint
新的类、接口和函数
弃用和向后不兼容
- 更合适的 Date/Time 异常。
- 现在在空数组中获取负索引
n
时,将确保下一个索引是n + 1
而不是0
。 - 对
range()
函数的更改。 - 在 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:默认错误模式设置为异常。