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

Що нового в PHP 8.0

  1. 01Named arguments: аргументи за назвою, а необовʼязкові можна просто пропустити.
  2. 02match, nullsafe ?-> і промоція властивостей у конструкторі прибирають шаблонний код.
  3. 03Union types, атрибути, WeakMap і JIT, а порівняння рядків з числами стало передбачуваним.
СТАТУС Не підтримується
Реліз
26 листопада 2020
Останній патч
8.0.30
Активна підтримка до
26.11.2022
Безпека до
26.11.2023
НОВІ МОЖЛИВОСТІ · 7

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

1.1 · RFC

Named arguments

Аргумент можна передати за іменем параметра, у будь-якому порядку, пропустивши необовʼязкові. Виклик з кількома bool і null читається без підглядання в сигнатуру. Працює і з вбудованими функціями, тому імена параметрів тепер стали частиною публічного API.

+ PHP 8.0
htmlspecialchars($text, double_encode: false);
− PHP 7.4
htmlspecialchars($text, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
1.2 · RFC

Атрибути

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

+ PHP 8.0
#[Route('/jobs', methods: ['POST'])]
public function store(): Response
− PHP 7.4
/**
 * @Route("/jobs", methods={"POST"})
 */
public function store(): Response
1.3 · RFC

Constructor property promotion

Модифікатор видимості перед параметром конструктора одразу оголошує властивість і записує в неї значення. Оголошення, параметр і присвоєння зливаються в один рядок, і DTO чи сервіс із залежностями стає втричі коротшим.

+ PHP 8.0
class Vacancy
{
    public function __construct(private string $title) {}
}
− PHP 7.4
class Vacancy
{
    private string $title;

    public function __construct(string $title)
    {
        $this->title = $title;
    }
}
1.4 · RFC

Union types

Параметр, властивість чи результат можуть мати один з кількох типів: int|float, string|null, Foo|Bar. Раніше це жило лише в @param, тепер тип перевіряється під час виконання. Для старих функцій, що повертають false замість результату, в union можна вказати псевдотип false.

+ PHP 8.0
public function format(int|float $amount): string
− PHP 7.4
/** @param int|float $amount */
public function format($amount): string
1.5 · RFC

Вираз match

match повертає значення, порівнює через === і не провалюється в наступну гілку. Кілька значень пишуться через кому в одній гілці. Якщо жодна не підійшла і default немає, летить UnhandledMatchError замість тихого null.

+ PHP 8.0
$label = match ($status) {
    200, 201 => 'ok',
    default => 'error',
};
− PHP 7.4
switch ($status) {
    case 200:
    case 201:
        $label = 'ok';
        break;
    default:
        $label = 'error';
}
1.6 · RFC

Nullsafe-оператор ?->

Якщо зліва від ?-> опинився null, решта ланцюжка не виконується, і весь вираз дає null. Окрема змінна й перевірка перед кожним викликом методу більше не потрібні. Разом з ?? виходить один рядок замість кількох if.

+ PHP 8.0
$city = $job->company()?->city;
− PHP 7.4
$company = $job->company();
$city = $company !== null ? $company->city : null;
1.7 · RFC

WeakMap

WeakMap використовує обʼєкти як ключі й не заважає збирачу сміття. Щойно на обʼєкт не лишилось інших посилань, запис зникає з мапи сам. Підходить для кешу й метаданих поруч із чужими обʼєктами, без витоку памʼяті в довгоживучих воркерах.

+ PHP 8.0
$cache = new WeakMap();
$cache[$request] = $result;
− PHP 7.4
// SplObjectStorage тримає обʼєкт, доки його не видалять вручну
$cache = new SplObjectStorage();
$cache[$request] = $result;
СИНТАКСИС · 6

Синтаксис

2.1 · RFC

Тип mixed

mixed приймає будь-яке значення, зокрема null. Від відсутнього типу він відрізняється наміром: читач і статичний аналіз бачать, що тип не забули, а свідомо дозволили все. Сигнатуру тепер можна типізувати повністю.

+ PHP 8.0
public function get(string $key): mixed
− PHP 7.4
/** @return mixed */
public function get(string $key)
2.2 · RFC

static як тип повернення

Тип static у поверненні означає обʼєкт того класу, через який викликано метод, з урахуванням наслідування. Fluent-білдери, незмінні обʼєкти з методами with*() і фабрики в базових класах отримують точний тип нащадка замість self.

+ PHP 8.0
public function withLimit(int $limit): static
− PHP 7.4
/** @return static */
public function withLimit(int $limit): self
2.3 · RFC

throw як вираз

throw став виразом, тому стоїть там, де очікується значення: після ??, у тернарному операторі, у стрілковій функції. Правило «значення або виняток» вміщається в один рядок без окремого if.

+ PHP 8.0
$value = $values[$key] ?? throw new RuntimeException("Немає змінної {$key}");
− PHP 7.4
$value = $values[$key] ?? null;

if ($value === null) {
    throw new RuntimeException("Немає змінної {$key}");
}
2.4 · RFC

$object::class

::class тепер працює і на змінній з обʼєктом, а не лише на імені класу. Результат той самий, що дає get_class(), а запис однаковий для класу й обʼєкта.

+ PHP 8.0
$class = $job::class;
− PHP 7.4
$class = get_class($job);
2.5 · RFC

catch без змінної

Якщо сам обʼєкт винятку не потрібен, змінну в catch можна не писати. Одразу видно, що виняток перехоплено свідомо, а лінтер не скаржиться на невикористану $e.

+ PHP 8.0
} catch (JsonException) {
    return null;
}
− PHP 7.4
} catch (JsonException $e) {
    return null;
}
2.6 · RFC

Кома після останнього параметра

Після останнього параметра функції чи останньої змінної в use тепер можна ставити кому. У багаторядкових сигнатурах новий параметр додає в diff один рядок, а не змінює два.

+ PHP 8.0
function vacancy(
    string $title,
    int $salary,
): string {
− PHP 7.4
function vacancy(
    string $title,
    int $salary
): string {
ФУНКЦІЇ · 4

Нові функції

3.1 · RFC

str_contains() і компанія

Три функції відповідають на найчастіші питання до рядка без хитрощів зі strpos() і substr(). Регістр має значення, а порожній рядок міститься в будь-якому, тому str_contains($s, '') дає true. З UTF-8 вони працюють коректно, mb-версії не потрібні.

+ PHP 8.0
if (str_contains($title, 'PHP')) { /* … */ }
if (str_starts_with($title, 'Senior')) { /* … */ }
− PHP 7.4
if (strpos($title, 'PHP') !== false) { /* … */ }
if (substr($title, 0, 6) === 'Senior') { /* … */ }
3.2 · RFC

get_debug_type()

gettype() повертає історичні назви на кшталт integer і double, а для обʼєкта просто object. get_debug_type() дає ті самі назви, що в типах і повідомленнях про помилки, тому годиться для винятків і логів.

+ PHP 8.0
$type = get_debug_type($value);
− PHP 7.4
$type = is_object($value) ? get_class($value) : gettype($value);
3.3 · RFC

Інтерфейс Stringable

Клас з методом __toString() автоматично реалізує Stringable. Тип string|Stringable приймає і рядок, і обʼєкт, що вміє ним ставати, без перевірки method_exists().

+ PHP 8.0
function label(string|Stringable $value): string
− PHP 7.4
/** @param string|object $value обʼєкт з __toString() */
function label($value): string
3.4 · НОВЕ

fdiv()

Оператор / у 8.0 кидає DivisionByZeroError при діленні на нуль. Коли потрібна математична семантика з нескінченністю, як у статистиці чи графіках, є fdiv(): вона повертає INF, -INF або NAN.

+ PHP 8.0
$ratio = fdiv($done, $total);
− PHP 7.4
$ratio = @($done / $total); // INF і warning при $total = 0
ПРОДУКТИВНІСТЬ · 1

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

4.1 · ДВИГУН

JIT-компілятор

JIT у складі OPcache перетворює байткод, що виконується найчастіше, на машинний код. Найбільше виграють обчислення на кшталт математики й парсерів, а типовий вебзастосунок, який чекає на базу, прискорюється помірно. Вмикається ненульовим opcache.jit_buffer_size.

+ PHP 8.0
opcache.enable=1
opcache.jit=tracing
opcache.jit_buffer_size=128M
− PHP 7.4
opcache.enable=1
; JIT немає, байткод виконує віртуальна машина
БЕЗПЕКА · 1

Безпека

5.1 · ЗМІНА

salt у password_hash() ігнорується

Опцію salt оголосили застарілою ще в 7.0, а з 8.0 password_hash() її ігнорує з попередженням. Сіль завжди береться з криптографічно стійкого генератора, тож слабку чи повторювану сіль з коду вже не передати. Старі хеші перевіряються як і раніше.

+ PHP 8.0
password_hash($password, PASSWORD_BCRYPT);
− PHP 7.4
password_hash($password, PASSWORD_BCRYPT, ['salt' => $salt]);
DEPRECATED

Застаріло

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

function f($a = 1, $b)Обовʼязковий параметр після необовʼязкового. Значення за замовчуванням тут нічого не дає, приберіть його.
ReflectionParameter::getClass()Разом з isArray() і isCallable(). Використовуйте getType().
usort() з bool у колбекуПорівняння має повертати число. Пишіть $a <=> $b замість $a > $b.
libxml_disable_entity_loader()PHP 8.0 вимагає libxml 2.9+, де зовнішні сутності й так не завантажуються. Виклик можна прибрати.
zip_open() і процедурний API zipВикористовуйте клас ZipArchive.
BREAKING

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

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

0 == 'foo' тепер falseЧисло з нечисловим рядком порівнюється як рядки. Перевірте in_array() і switch з рядками.
TypeError і ValueError у вбудованих функціяхНеправильний тип чи значення аргументу кидає виняток замість warning і null.
Арифметика з масивами й обʼєктами[] % 2 чи new stdClass + 1 кидають TypeError, так само як 'abc' * 2 з нечисловим рядком.
Ділення на нуль кидає DivisionByZeroError1 / 0 більше не повертає INF з warning. Для IEEE-семантики є fdiv().
@ не глушить фатальні помилкиerror_reporting() в обробнику під @ тепер повертає 4437 замість 0, тож перевірки на === 0 у власних обробниках зламаються.
each(), create_function() та інші видалені функціїПрибрано те, що застаріло в 7.x, зокрема each(), create_function(), money_format() і get_magic_quotes_gpc().
error_reporting = E_ALL за замовчуваннямNotice і Deprecated видно без налаштувань, а display_startup_errors увімкнено.
Сигнатури абстрактних методів трейтівРеалізація абстрактного методу з трейту тепер мусить мати сумісну сигнатуру.

Як оновитися

0 / 6