<? phpukraine ЕКОСИСТЕМА
⌕Пошук по платформі
PHP · ЩО НОВОГО

Що нового в PHP 8.4

  1. 01Property hooks: логіка get і set прямо у властивості, без гетерів і сетерів.
  2. 02Асиметрична видимість: читати публічно, змінювати лише зсередини класу.
  3. 03Lazy objects, array_find() і компанія, BcMath\Number з операторами та атрибут
СТАТУС Активна підтримка
Реліз
21 листопада 2024
Останній патч
8.4.26
Активна підтримка до
31.12.2026
Безпека до
31.12.2028
НОВІ МОЖЛИВОСТІ · 5

Нові можливості

1.1 · RFC

Property hooks

Гетер і сетер тепер описуються прямо у властивості. Зовні це звичайне поле, а нормалізація чи обчислення живуть поруч із ним, а не в парі методів. Хук може бути лише на get, лише на set або на обидва, а властивість без власного значення стає віртуальною.

+ PHP 8.4
public string $name {
    set => ucfirst(trim($value));
}
− PHP 8.3
private string $name;

public function setName(string $value): void
{
    $this->name = ucfirst(trim($value));
}
1.2 · RFC

Асиметрична видимість

Властивість може бути публічною на читання і приватною чи захищеною на запис. Більше не потрібен приватний стан плюс публічний гетер лише для того, щоб заборонити зміну ззовні. З промоцією в конструкторі виходить коротко й чесно.

+ PHP 8.4
public private(set) int $total = 0;
− PHP 8.3
private int $total = 0;

public function total(): int
{
    return $this->total;
}
1.3 · RFC

Lazy objects

Ядро вміє створювати «ліниві» обʼєкти: ghost ініціалізує сам себе, proxy підставляє справжній екземпляр. Раніше це робили генерацією коду в Doctrine чи Symfony, тепер це звичайний виклик ReflectionClass. Важкий конструктор не виконується, поки обʼєкт не знадобився.

+ PHP 8.4
$report = (new ReflectionClass(Report::class))
    ->newLazyGhost(fn (Report $r) => $r->__construct($rows));
− PHP 8.3
// генерований proxy-клас від бібліотеки
$report = $factory->createProxy(Report::class, $init);
1.4 · RFC

#[\Deprecated]

Атрибут вмикає для вашого коду те саме попередження Deprecated, що й у вбудованих функцій. Не треба вручну викликати trigger_error(), а IDE й статичний аналіз бачать позначку з повідомленням і версією.

+ PHP 8.4
#[\Deprecated(message: 'використовуйте send()', since: '2.0')]
public function sendNow(): void { /* … */ }
− PHP 8.3
public function sendNow(): void
{
    trigger_error('Use send()', E_USER_DEPRECATED);
}
1.5 · RFC

BcMath\Number

Гроші й інші точні обчислення більше не потребують ланцюжків bcadd() і bcmul() з рядками. BcMath\Number працює з +, -, *, / і порівнянням, незмінний і сам тримає масштаб. Помилок округлення float тут немає.

+ PHP 8.4
use BcMath\Number;

$total = new Number('19.99') * 3 + new Number('4.50');
− PHP 8.3
$total = bcadd(bcmul('19.99', '3', 2), '4.50', 2);
СИНТАКСИС · 1

Синтаксис

2.1 · RFC

new без дужок

Метод, властивість чи константу можна взяти одразу зі створеного обʼєкта, не обгортаючи new в додаткові дужки. Дрібниця, але її пишуть у кожному білдері й тесті.

+ PHP 8.4
new Request()->validate();
− PHP 8.3
(new Request())->validate();
ФУНКЦІЇ · 5

Нові функції

3.1 · RFC

array_find() і друзі

Чотири функції для частих задач: array_find() повертає перший елемент за умовою, array_find_key() його ключ, array_any() каже, чи підходить хоч один, а array_all() чи підходять усі. Замість foreach з break або array_filter() з reset().

+ PHP 8.4
$first = array_find($jobs, fn ($job) => str_starts_with($job, 'Senior'));
− PHP 8.3
$first = null;
foreach ($jobs as $job) {
    if (str_starts_with($job, 'Senior')) {
        $first = $job;
        break;
    }
}
3.2 · RFC

mb_trim() і mb_ucfirst()

Нарешті є mb_trim(), mb_ltrim() і mb_rtrim(), які прибирають і юнікодні пробіли на кшталт нерозривного, та mb_ucfirst() з mb_lcfirst(). ucfirst() з кирилицею нічого не робив, бо працює з байтами.

+ PHP 8.4
mb_ucfirst($city);
− PHP 8.3
mb_strtoupper(mb_substr($city, 0, 1)) . mb_substr($city, 1);
3.3 · RFC

RoundingMode для round()

round() приймає новий enum RoundingMode. До звичних режимів додались TowardsZero, AwayFromZero, PositiveInfinity і NegativeInfinity, тож округлення вгору чи вниз з точністю не треба збирати з ceil() і множення.

+ PHP 8.4
$up = round($price, 2, RoundingMode::PositiveInfinity);
− PHP 8.3
$up = ceil($price * 100) / 100;
3.4 · НОВЕ

DateTime::createFromTimestamp()

Створити дату з мітки часу можна прямим методом, і він приймає float з мікросекундами. Разом із ним зʼявились getMicrosecond() і setMicrosecond().

+ PHP 8.4
$at = DateTimeImmutable::createFromTimestamp($timestamp);
− PHP 8.3
$at = new DateTimeImmutable('@' . $timestamp);
3.5 · RFC

HTML5 у DOM

Новий простір імен Dom з класами HTMLDocument і XMLDocument. HTML5 тепер розбирається за стандартом, без попереджень про невідомі теги, а querySelector() з CSS-селекторами працює з коробки. Старий DOMDocument лишається для сумісності.

+ PHP 8.4
$doc = Dom\HTMLDocument::createFromString($html);
$title = $doc->querySelector('h1')->textContent;
− PHP 8.3
$doc = new DOMDocument();
@$doc->loadHTML($html);
ПРОДУКТИВНІСТЬ · 1

Продуктивність

4.1 · ДВИГУН

Новий JIT на основі IR

JIT переписано на проміжне представлення IR. Він простіший у підтримці й дає основу для майбутніх оптимізацій. Вмикається тими самими налаштуваннями opcache.jit.

+ PHP 8.4
opcache.jit=tracing
opcache.jit_buffer_size=64M
; та сама конфігурація, новий двигун
− PHP 8.3
opcache.jit=tracing
opcache.jit_buffer_size=64M
БЕЗПЕКА · 1

Безпека

5.1 · ЗМІНА

bcrypt cost 12 за замовчуванням

password_hash() з PASSWORD_BCRYPT тепер за замовчуванням використовує cost 12 замість 10. Хеші стійкіші до перебору, а старі продовжують перевірятися без змін. password_needs_rehash() підкаже, які варто оновити при наступному вході.

+ PHP 8.4
password_hash($password, PASSWORD_BCRYPT);
// $2y$12$...
− PHP 8.3
password_hash($password, PASSWORD_BCRYPT);
// $2y$10$...
DEPRECATED

Застаріло

Ще працює, але дає попередження і зникне в одній із наступних версій.

string $x = nullНеявно nullable параметр. Пишіть ?string $x = null.
E_STRICTКонстанта застаріла, цей рівень помилок давно не використовується.
trigger_error(…, E_USER_ERROR)Кидайте виняток замість фатальної помилки з коду.
lcg_value()Використовуйте Random\Randomizer::getFloat().
_ як назва класуПідкреслення зарезервоване під майбутні можливості мови.
BREAKING

Ламає сумісність

Перевірте це до оновлення: такий код перестане працювати або поводитиметься інакше.

ext/imap, ext/oci8, ext/pspellВинесено з ядра в PECL. Встановіть окремо, якщо користуєтесь.
exit() як функціяТепер справжня функція, тож передача масиву чи обʼєкта дає TypeError.
round() з невідомим режимомНеприпустимий $mode кидає ValueError замість того, щоб тихо ігноруватися.

Як оновитися

0 / 5