PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

PHP 8.0 preview – union types, named arguments, match, constructor promotion, JIT

by Henryk Tews / Tuesday, 14 July 2020 / Published in PHP

PHP 8.0 ma wyjść w listopadzie 2020 i będzie największą zmianą w języku od czasu PHP 7.0. JIT compiler, union types, named arguments, match expression, constructor property promotion – to nie są drobne poprawki. Przeglądam najważniejsze nowości na przykładach i oceniam co realne znaczenie dla codziennego kodu z Magento 2.

Union Types – wiele typów w jednej deklaracji

Do tej pory jedyną opcją połączenia typów był nullable type (?string). PHP 8.0 pozwala deklarować pełne uniony:

<?php

declare(strict_types=1);

// PHP 7.x - brak możliwości wyrażenia "int lub float"
// trzeba było używać docblocka i liczyć na IDE

// PHP 8.0 - union type w sygnaturze
function calculatePrice(int|float $basePrice, int|float $taxRate): float
{
    return (float) ($basePrice * (1 + $taxRate));
}

calculatePrice(100, 0.23);   // ok
calculatePrice(99.99, 0.23); // ok
calculatePrice('100', 0.23); // TypeError w strict_types

// Przydatne przy metodach akceptujących int lub string ID
function findProduct(int|string $identifier): ?ProductInterface
{
    if (is_int($identifier)) {
        return $this->productRepository->getById($identifier);
    }

    return $this->productRepository->get($identifier); // pobierz po SKU
}

Named Arguments – koniec z tajemniczymi true/false

Named arguments pozwalają przekazywać argumenty po nazwie zamiast po pozycji. Eliminuje jeden z najbardziej irytujących anty-wzorców w PHP:

<?php

// PHP 7.x - co znaczy to "true, false, null"?
$product = $productRepository->getById(42, true, null, false);

// PHP 8.0 - czytelne nazwane argumenty
$product = $productRepository->getById(
    id: 42,
    editMode: true,
    storeId: null,
    forceReload: false
);

// Kolejność nie ma znaczenia przy named arguments
array_slice(array: $items, offset: 2, length: 5, preserve_keys: true);

// Szczególnie przydatne przy funkcjach z wieloma opcjonalnymi parametrami
implode(separator: ', ', array: ['PHP', 'Magento', 'MySQL']);

Match Expression – switch bez pułapek

match to ulepszona wersja switch: używa strict comparison, zwraca wartość, nie wymaga break i rzuca UnhandledMatchError gdy żaden przypadek nie pasuje:

<?php

// switch - luźne porównanie, łatwo o bug
$status = '1'; // string
switch ($status) {
    case 1:     // true! switch używa ==
        echo 'active';
        break;
}

// match - strict comparison, zwraca wartość
$statusLabel = match((int) $status) {
    1       => 'Aktywny',
    2       => 'Nieaktywny',
    3, 4    => 'Oczekuje',  // kilka wartości naraz
    default => throw new \InvalidArgumentException("Unknown status: {$status}"),
};

// W Magento 2 - przykład w resolverze
$visibility = match($product->getVisibility()) {
    1 => 'Not Visible Individually',
    2 => 'Catalog',
    3 => 'Search',
    4 => 'Catalog, Search',
    default => 'Unknown',
};

Constructor Property Promotion

Eliminuje powtarzanie właściwości w trzech miejscach – deklaracja, parametr konstruktora, przypisanie:

<?php

declare(strict_types=1);

// PHP 7.4 - trzy miejsca dla każdej właściwości
class ApiClient
{
    private string $baseUrl;
    private int $timeout;
    private \Psr\Log\LoggerInterface $logger;

    public function __construct(
        string $baseUrl,
        int $timeout,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->baseUrl = $baseUrl;
        $this->timeout = $timeout;
        $this->logger  = $logger;
    }
}

// PHP 8.0 - jedno miejsce
class ApiClient
{
    public function __construct(
        private string $baseUrl,
        private int $timeout = 30,
        private \Psr\Log\LoggerInterface $logger
    ) {}
}

W Magento 2 constructor promotion jest wygodny, ale ma jedno ograniczenie – Magento’s Object Manager działa przez refleksję i analizuje konstruktory. W praktyce promotion działa poprawnie z DI od Magento 2.4.x wzwyż, które oficjalnie wspiera PHP 8.0.

Nullsafe Operator

Operator ?-> przerywa łańcuch wywołań gdy napotka null, zamiast rzucać błąd:

<?php

// PHP 7.x - piramida sprawdzeń null
$city = null;
if ($order !== null) {
    $address = $order->getShippingAddress();
    if ($address !== null) {
        $region = $address->getRegion();
        if ($region !== null) {
            $city = $region->getCity();
        }
    }
}

// PHP 8.0 - nullsafe operator
$city = $order?->getShippingAddress()?->getRegion()?->getCity();
// Jeśli cokolwiek po drodze zwróci null - $city = null, bez błędu

JIT Compiler – dla kogo realna różnica?

JIT (Just-In-Time compilation) kompiluje kod PHP do kodu maszynowego w runtime. Dla typowych aplikacji webowych – Magento, Symfony, Laravel – różnica jest minimalna, bo wąskim gardłem jest I/O (baza, sieć), nie obliczenia CPU. JIT błyszczy przy zadaniach numerycznych, przetwarzaniu obrazów, algorytmach – czyli wszędzie tam gdzie PHP wykonuje dużo obliczeń bez czekania na zewnętrzne zasoby.

// php.ini - włączenie JIT
opcache.enable=1
opcache.jit_buffer_size=100M
opcache.jit=tracing  // tryb tracing - najlepszy dla większości zastosowań

Dla Magento 2 nie spodziewaj się dramatycznej poprawy wydajności po włączeniu JIT. Optymalizacja zapytań do bazy i konfiguracja Varnish/Redis dadzą znacznie więcej.

Podsumowanie

PHP 8.0 to solidny krok naprzód. Named arguments i match expression wchodzą do codziennego kodu niemal natychmiast – są wstecznie kompatybilne z istniejącą logiką. Constructor property promotion czyści konstruktory w nowym kodzie. Union types wymuszają myślenie o typach tam gdzie wcześniej uciekało się do docblocka. Magento 2.4.x oficjalnie wspiera PHP 8.0 – migracja jest możliwa, choć wymaga przeglądu zewnętrznych modułów pod kątem kompatybilności.

About Henryk Tews

What you can read next

PHP 7.2 – object type hint, sodium instead of mcrypt, deprecations

© 2026 Created by

TOP
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Always active
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
Zobacz preferencje
  • {title}
  • {title}
  • {title}