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

Що нового в PHP 8.2

  1. 01readonly класи: одне слово перед class, і всі властивості незмінні.
  2. 02DNF-типи на кшталт (A&B)|null, а null, false і true стали самостійними типами.
  3. 03Розширення Random, константи в трейтах і #[\SensitiveParameter], а динамічні властивості тепер Deprecated.
СТАТУС Лише безпека
Реліз
8 грудня 2022
Останній патч
8.2.34
Активна підтримка до
31.12.2024
Безпека до
31.12.2026
НОВІ МОЖЛИВОСТІ · 3

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

1.1 · RFC

readonly класи

Модифікатор readonly перед class робить readonly кожну оголошену властивість, тож у DTO і value object його не треба повторювати в кожному рядку конструктора. Властивості мають бути типізовані, динамічні властивості заборонені, а успадкувати такий клас може лише інший readonly клас.

+ PHP 8.2
readonly class Money
{
    public function __construct(
        public int $amount,
        public string $currency,
    ) {}
}
− PHP 8.1
class Money
{
    public function __construct(
        public readonly int $amount,
        public readonly string $currency,
    ) {}
}
1.2 · RFC

Random\Randomizer

Нове розширення random збирає генератори випадкових чисел в обʼєкти. Randomizer має getInt(), shuffleArray(), pickArrayKeys() і getBytes(), а двигун обираєте самі: Mt19937, PcgOneseq128XslRr64, Xoshiro256StarStar або криптостійкий Secure, який стоїть за замовчуванням. Сід живе в обʼєкті, тож тест з фіксованим сідом відтворюваний і не залежить від mt_srand() деінде в коді.

+ PHP 8.2
use Random\Engine\Xoshiro256StarStar;
use Random\Randomizer;

$random = new Randomizer(new Xoshiro256StarStar(2022));
$number = $random->getInt(1, 100);
− PHP 8.1
mt_srand(2022);
$number = mt_rand(1, 100);
1.3 · RFC

Константи в трейтах

Раніше трейт не міг мати констант, і їх виносили в інтерфейс або дублювали в кожному класі, що використовує трейт. Тепер константа живе поруч з методами, яким вона потрібна. Читати її треба через клас: звернення через назву трейта кидає Error.

+ PHP 8.2
trait HasStatus
{
    public const DEFAULT_STATUS = 'draft';
}
− PHP 8.1
interface StatusDefaults
{
    public const DEFAULT_STATUS = 'draft';
}

class Post implements StatusDefaults
{
    use HasStatus;
}
СИНТАКСИС · 3

Синтаксис

2.1 · RFC

DNF-типи

У PHP 8.1 перетин A&B не можна було поєднати з іншим типом, навіть з null. DNF-типи (disjunctive normal form) дозволяють обʼєднувати перетини, взяті в дужки, тож (A&B)|null чи (A&B)|C пишуться в сигнатурі, а не лише в PHPDoc.

+ PHP 8.2
function label((HasId&HasName)|null $entity): string
− PHP 8.1
/** @param (HasId&HasName)|null $entity */
function label($entity): string
2.2 · RFC

null, false і true як типи

false і null тепер можна писати як окремі типи, а не лише в обʼєднанні, і додався тип true. Сигнатура точніше каже, що повертає метод: реалізація інтерфейсу з bool, яка завжди відповідає true, може звузити тип до true.

+ PHP 8.2
public function isEnabled(): true
{
    return true;
}
− PHP 8.1
public function isEnabled(): bool
{
    return true;
}
2.3 · RFC

Властивості enum у константах

У константних виразах тепер можна читати name і value кейсів enum. Константа класу, значення параметра за замовчуванням чи аргумент атрибута беруть Status::Active->value напряму, без копії рядка 'active', яка рано чи пізно розійдеться з enum.

+ PHP 8.2
class Job
{
    public const DEFAULT_STATUS = Status::Active->value;
}
− PHP 8.1
class Job
{
    public const DEFAULT_STATUS = 'active';
}
ФУНКЦІЇ · 5

Нові функції

3.1 · НОВЕ

Модифікатор n у preg_*

Модифікатор n (NO_AUTO_CAPTURE) робить звичайні групи в дужках незахоплюючими, тож у $matches потрапляють лише іменовані. Більше не треба ставити ?: у кожну групу, написану тільки для чергування чи квантифікатора.

+ PHP 8.2
preg_match('/(\d{4})-(\d{2})-(?<day>\d{2})/n', $date, $m);
− PHP 8.1
preg_match('/(?:\d{4})-(?:\d{2})-(?<day>\d{2})/', $date, $m);
3.2 · НОВЕ

ini_parse_quantity()

ini_get() повертає memory_limit чи upload_max_filesize рядком на кшталт '256M'. ini_parse_quantity() перетворює його на байти за тими ж правилами, що й сам PHP, разом із суфіксами K, M, G і префіксами 0x, 0o, 0b. Саморобний розбір за останньою літерою більше не потрібен.

+ PHP 8.2
$bytes = ini_parse_quantity(ini_get('upload_max_filesize'));
− PHP 8.1
$limit = ini_get('upload_max_filesize');
$bytes = match (strtoupper(substr($limit, -1))) {
    'G' => (int) $limit * 1024 ** 3,
    'M' => (int) $limit * 1024 ** 2,
    'K' => (int) $limit * 1024,
    default => (int) $limit,
};
3.3 · НОВЕ

memory_reset_peak_usage()

memory_get_peak_usage() рахує пік від старту процесу, тож у воркері черги після однієї важкої задачі цифра вже не змінюється. memory_reset_peak_usage() скидає пік до поточного використання, і памʼять кожної задачі видно окремо.

+ PHP 8.2
memory_reset_peak_usage();
$job->handle();
$peak = memory_get_peak_usage();
− PHP 8.1
$job->handle();
// пік з моменту старту процесу, разом з усіма попередніми задачами
$peak = memory_get_peak_usage();
3.4 · RFC

iterator_to_array() для масивів

Параметр з типом iterable приймає і масив, і генератор, але iterator_to_array() на масиві падав з TypeError. Тепер обидві функції приймають будь-який iterable, і перевірка is_array() перед викликом зайва.

+ PHP 8.2
return iterator_to_array($users, false);
− PHP 8.1
return is_array($users)
    ? array_values($users)
    : iterator_to_array($users, false);
3.5 · RFC

mysqli_execute_query()

mysqli_execute_query() і метод mysqli::execute_query() готують запит, привʼязують параметри, виконують його і повертають результат. Замість prepare(), bind_param(), execute() і get_result() один рядок, а параметри так само йдуть окремо від SQL.

+ PHP 8.2
$result = $mysqli->execute_query('SELECT * FROM jobs WHERE city = ?', [$city]);
− PHP 8.1
$stmt = $mysqli->prepare('SELECT * FROM jobs WHERE city = ?');
$stmt->bind_param('s', $city);
$stmt->execute();
$result = $stmt->get_result();
БЕЗПЕКА · 2

Безпека

4.1 · RFC

#[\SensitiveParameter]

Аргументи функцій потрапляють у стек-трейси винятків, а звідти в логи й Sentry. Параметр з атрибутом #[\SensitiveParameter] у трейсі замінюється обʼєктом SensitiveParameterValue, тож пароль чи API-ключ не витече разом з помилкою.

+ PHP 8.2
function login(string $user, #[\SensitiveParameter] string $password): void
// #0 login('olena', Object(SensitiveParameterValue))
− PHP 8.1
function login(string $user, string $password): void
// #0 login('olena', 'qwerty123')
4.2 · НОВЕ

openssl_cipher_key_length()

openssl_cipher_key_length() повертає потрібну довжину ключа для шифру, тож її не треба тримати в коді числом поруч із назвою алгоритму. Також openssl_encrypt() тепер підтримує chacha20-poly1305 як AEAD з тегом автентифікації, так само як aes-256-gcm.

+ PHP 8.2
$cipher = 'chacha20-poly1305';
$key = random_bytes(openssl_cipher_key_length($cipher));
$encrypted = openssl_encrypt($data, $cipher, $key, 0, $nonce, $tag);
− PHP 8.1
$key = random_bytes(32); // довжина для aes-256-gcm
$encrypted = openssl_encrypt($data, 'aes-256-gcm', $key, 0, $iv, $tag);
DEPRECATED

Застаріло

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

Динамічні властивостіОголосіть властивість або додайте класу #[\AllowDynamicProperties]. stdClass і __set() це не зачіпає.
"${var}" у рядкахПишіть "$var" або "{$var}", а "${expr}" замініть на "{${expr}}".
utf8_encode() і utf8_decode()Вони вміють лише Latin-1. Використовуйте mb_convert_encoding().
Callable "self::method"Рядки й масиви з self, parent чи static. Пишіть self::method(...) або [self::class, 'method'].
QPrint, Base64, Uuencode і HTML-ENTITIES у mbstringДля цього є base64_encode(), quoted_printable_encode(), convert_uuencode() і htmlentities().
BREAKING

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

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

strtolower() і strtoupper() без локаліТепер завжди лише ASCII, що б не стояло в setlocale(). Так само ucfirst(), stripos() і str_ireplace().
str_split('')Повертає порожній масив замість [''].
ksort() з мішаними ключамиЧислові й рядкові ключі порівнюються за правилами PHP 8, тож порядок змінився.
var_export() з \ перед класомІмена класів тепер повністю кваліфіковані, тож згенерований код у namespace змінився.

Як оновитися

0 / 6