Statement on glibc/iconv Vulnerability
Випущено!
PHP 8.3 — це значне оновлення мови PHP.
Воно містить багато нових можливостей, таких як явна типізація констант класів, глибоке клонування readonly-властивостей і доповнення до функціоналу генерування випадкових чисел. Як завжди, воно також включає покращення продуктивності, виправлення помилок і загальний рефакторинг.

Типізовані константи класу 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 буде впевнюватися, що метод із такою ж назвою існує у батьківському класі або реалізованому інтерфейсі. Додавання цього атрибута дає можливість зрозуміти, що перевизначення батьківського методу є навмисним і спрощує рефакторинг, оскільки видалення перевизначеного батьківського методу не залишиться непоміченим.

Глибоке клонування readonly-властивостей 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;
Модуль Random, що додано у PHP 8.2, було розширено новим методом генерування випадкових рядків, які складаються лише з певних байтів. Цей метод дозволяє розробнику легко генерувати випадкові ідентифікатори, такі як імена доменів і числові рядки довільної довжини.

Нові методи 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() використовує алгоритм y-section, який було опубліковано у статті Drawing Random Floating-Point Numbers from an Interval. Frédéric Goualard, ACM Trans. Model. Comput. Simul., 32:3, 2022.

Лінтер командного рядка підтримує можливість перевірки декількох файлів 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

Лінтер командного рядка тепер може приймати декілька імен файлів для перевірки

Нові класи, інтерфейси та функції

Застаріла функціональність і зміни у зворотній сумісності

  • Доречніші винятки у модулі Date/Time.
  • Присвоєння від'ємного індексу n до порожнього масиву тепер гарантує, що наступним індексом буде n + 1 замість 0.
  • Внесено зміни до функціїrange().
  • Зміни у повторному оголошенні статичних властивостей у трейтах.
  • Константу U_MULTIPLE_DECIMAL_SEPERATORS оголошено застарілою, натомість рекомендується використовувати U_MULTIPLE_DECIMAL_SEPARATORS.
  • Механізм Mt19937 MT_RAND_PHP оголошено застарілим.
  • ReflectionClass::getStaticProperties() тепер не повертає значення null.
  • Параметри INI assert.active, assert.bail, assert.callback, assert.exception і assert.warning оголошено застарілими.
  • Можливість виклику функції get_class() і get_parent_class() без аргументів оголошено застарілою.
  • SQLite3: Режим помилок за замовчуванням встановлено на винятки.
To Top