PHP 8 (od 8.0 z listopada 2020 do 8.5 z listopada 2025) przyniosłomatch, nazwane argumenty, atrybuty, enumy, klasyreadonlyi, od 8.4, property hooks. Szybsze działanie wynika głównie z kolejnych optymalizacji silnika, a JIT pomaga przede wszystkim w obliczeniach, nie w typowej aplikacji webowej. Dziś warto korzystać z wersji 8.4 lub 8.5, bo 8.1 nie dostaje już poprawek bezpieczeństwa.
Ósemka nie jest jednym wydaniem, tylko całą serią: od 8.0 do 8.5 co roku w listopadzie wychodziła nowa wersja z własnym zestawem zmian. Poniżej przechodzimy po nich w kolejności, a na końcu sprawdzamy, co z wydajnością i jak zaktualizować projekt. Przykłady uruchomiliśmy w PHP 8.4.5; fragmenty dotyczące 8.5 pochodzą z oficjalnej dokumentacji i tego nie sprawdzaliśmy lokalnie.
Jakie wersje PHP 8 są dziś wspierane?
PHP wydaje nową wersję co roku. Każda ma dwa lata aktywnego wsparcia i dwa lata poprawek bezpieczeństwa. Stan na 11 listopada 2026, według php.net:
| Wersja | Premiera | Koniec aktywnego wsparcia | Koniec poprawek bezpieczeństwa |
|---|---|---|---|
| 8.1 | 25 listopada 2021 | 25 listopada 2023 | 31 grudnia 2025 (zakończone) |
| 8.2 | 8 grudnia 2022 | 31 grudnia 2024 | 31 grudnia 2026 |
| 8.3 | 23 listopada 2023 | 31 grudnia 2025 | 31 grudnia 2027 |
| 8.4 | 21 listopada 2024 | 31 grudnia 2026 | 31 grudnia 2028 |
| 8.5 | 20 listopada 2025 | 31 grudnia 2027 | 31 grudnia 2029 |
Wersja 8.6 jest w fazie kandydata do wydania (RC), więc nie omawiamy jej tutaj.
Co przyniosło PHP 8.0?
To największy skok w całej serii. Zmieniło sposób, w jaki pisze się kod, i dlatego jest najczęściej pytane na rozmowach.
Czym jest match i czym różni się od switch?
match jest wyrażeniem, czyli zwraca wartość, porównuje ściśle (===) i nie potrzebuje break. Gdy nic nie pasuje, a nie ma gałęzi default, rzuca UnhandledMatchError.
function label(int $code): string {
return match (true) {
$code >= 500 => 'błąd serwera',
$code >= 400 => 'błąd klienta',
$code >= 200 => 'sukces',
default => 'inne',
};
}
echo label(404); // błąd klienta
Do czego służą nazwane argumenty?
Pozwalają przekazać argument po nazwie, pomijając te, które mają wartość domyślną. Kod staje się czytelniejszy przy funkcjach z wieloma parametrami opcjonalnymi:
function makeUrl(string $host, bool $secure = true, int $port = 443): string {
return ($secure ? 'https' : 'http') . "://$host:$port";
}
echo makeUrl('devmentor.pl', port: 8443); // https://devmentor.pl:8443
Uwaga przy aktualizacji: nazwy parametrów stały się częścią publicznego API funkcji. Zmiana nazwy w bibliotece może więc zepsuć cudzy kod.
Co jeszcze weszło w 8.0?
- Constructor promotion — pola klasy deklarujesz i przypisujesz w sygnaturze konstruktora, bez powtarzania ich w ciele klasy.
- Union types —
int|floatw typach parametrów i wartości zwracanych. - Operator nullsafe
?->— przerywa łańcuch wywołań, gdy któryś element tonull, zamiast rzucać błąd. - Atrybuty (
#[...]) — metadane w kodzie zamiast adnotacji w komentarzach. Z tego korzystają dziś m.in. frameworki do routingu. - Nowe funkcje tekstowe —
str_contains,str_starts_with,str_ends_with. - JIT — kompilator just-in-time, o którym piszemy niżej.
Co zmieniło się w porównywaniu tekstu z liczbą?
Wyrażenie 0 == "a" w PHP 7 dawało true, a od PHP 8 daje false. To zmiana, która po aktualizacji potrafi odkryć błędy ukryte w starej logice. Szczegółowo o tym i podobnych pułapkach piszemy w pytaniach rekrutacyjnych z PHP.
Co przyniosło PHP 8.1?
Jak działają enumy w PHP?
Enum to typ o skończonej liście wartości. Wersja z wartościami (backed enum) mapuje je na string lub int, a sam enum może mieć metody:
enum Status: string {
case Draft = 'draft';
case Published = 'published';
public function label(): string {
return match ($this) {
self::Draft => 'Szkic',
self::Published => 'Opublikowany',
};
}
}
echo Status::from('draft')->label(); // Szkic
var_dump(Status::tryFrom('x')); // NULL
Czym jest właściwość readonly?
Właściwość oznaczona readonly można ustawić tylko raz, zwykle w konstruktorze. Próba zmiany kończy się błędem Cannot modify readonly property.
final class Product {
public function __construct(
public readonly string $name,
public readonly int $price,
) {}
}
Co jeszcze weszło w 8.1?
- First-class callable —
strlen(...)tworzy domknięcie z istniejącej funkcji. - Typ zwracany
never— dla funkcji, które nigdy nie wracają (rzucają wyjątek albo kończą skrypt). - Fibers — niskopoziomowy mechanizm współbieżności, na którym budują się biblioteki asynchroniczne. W codziennym kodzie aplikacyjnym raczej ich nie użyjesz bezpośrednio.
Co przyniosło PHP 8.2 i 8.3?
W 8.2 pojawiły się klasy readonly, czyli cała klasa z niezmiennymi właściwościami, oraz typy null i false jako samodzielne. Jednocześnie 8.2 zaczęło oznaczać jako przestarzałe tworzenie właściwości dynamicznych, co dla starszych projektów jest najczęstszym źródłem ostrzeżeń po aktualizacji.
readonly class Point {
public function __construct(public int $x, public int $y) {}
}
W 8.3 dodano typowane stałe klas (public const string NAME = 'c';), funkcję json_validate(), która sprawdza poprawność JSON-a bez dekodowania go do pamięci, oraz atrybut #[\Override], który pilnuje, żeby metoda faktycznie nadpisywała metodę rodzica.
Co przyniosło PHP 8.4?
Czym są property hooks?
Hooki pozwalają zdefiniować get i set bezpośrednio przy właściwości, bez osobnych metod. Dla wartości wyliczanych zastępują klasyczne gettery:
class User {
public string $fullName {
get => $this->first . ' ' . $this->last;
}
public function __construct(
public string $first,
public string $last,
) {}
}
echo (new User('Jan', 'Kowalski'))->fullName; // Jan Kowalski
Czym jest asymetryczna widoczność?
Możesz ustawić inną widoczność dla odczytu i zapisu. Najczęściej: publiczny odczyt, prywatny zapis.
class Account {
public private(set) int $balance = 0;
public function deposit(int $amount): void {
$this->balance += $amount;
}
}
$account = new Account();
$account->deposit(10);
echo $account->balance; // 10
// $account->balance = 99; → Error: Cannot modify private(set) property
Co jeszcze weszło w 8.4?
newbez dodatkowych nawiasów —new DateTime('2026-01-01')->format('Y')zamiast(new DateTime(...))->format('Y').- Nowe funkcje tablicowe —
array_find(),array_any(),array_all().
Co przyniosło PHP 8.5?
Wersja z 20 listopada 2025. Według oficjalnej strony PHP najważniejsze zmiany to:
- Pipe operator
|>— łańcuch wywołań czytany od lewej do prawej zamiast zagnieżdżonych funkcji. - Rozszerzenie URI — wbudowane parsowanie i normalizacja adresów zgodna z RFC 3986 i standardem WHATWG, w miejsce ograniczonego
parse_url(). clonez nadpisaniem właściwości —clone($obiekt, ['alpha' => 128]), wygodne dla klasreadonly.- Atrybut
#[\NoDiscard]— ostrzeżenie, gdy ktoś zignoruje zwróconą wartość funkcji. - Domknięcia w wyrażeniach stałych — np. w parametrach atrybutów.
$title = ' PHP 8.5 Released ';
$slug = $title
|> trim(...)
|> (fn($str) => str_replace(' ', '-', $str))
|> (fn($str) => str_replace('.', '', $str))
|> strtolower(...);
// string(15) "php-85-released"
Czy PHP 8 jest szybsze od PHP 7?
Krótko: tak, ale nie spodziewaj się cudów. Największy skok wydajności to przejście z PHP 5.6 na 7.0, a nie z 7.4 na 8.0. Kolejne wersje 8.x przynoszą stopniowe optymalizacje silnika, w tym mniejsze zużycie pamięci i szybsze operacje na tablicach i tekście.
Co daje JIT w PHP 8?
JIT kompiluje fragmenty kodu do instrukcji procesora w czasie działania. Najwięcej zyskują zadania obciążające procesor: obliczenia numeryczne, przetwarzanie obrazów, symulacje. W typowej aplikacji webowej, która głównie czeka na bazę danych i sieć, JIT zmienia niewiele. Domyślnie nie jest też włączony: trzeba go skonfigurować w ustawieniach OPcache (opcache.jit i opcache.jit_buffer_size). W naszym środowisku testowym z PHP 8.4.5 wartość opcache.jit wynosiła disable.
Jak sprawdzić wydajność we własnym projekcie?
Zamiast wierzyć ogólnym liczbom, zmierz swój przypadek: ten sam kod i te same dane na dwóch wersjach PHP (np. w dwóch kontenerach), obciążenie narzędziem typu ab, wrk lub k6, a do profilowania Xdebug albo Blackfire. Dopiero wtedy wiesz, czy wąskim gardłem jest PHP, czy baza.
Jak bezpiecznie przejść na nowszą wersję PHP?
Po pierwsze, nie przeskakuj od razu kilku wersji w produkcji. Najpierw zaktualizuj środowisko deweloperskie i testowe.
- Sprawdź zgodność zależności.
composer why-not php 8.4pokaże, które pakiety blokują aktualizację. - Uruchom statyczną analizę. PHPStan i Psalm wyłapują wywołania usuniętych funkcji i niezgodności typów.
- Automatyzuj zmiany. Rector potrafi przepisać kod pod nowszą wersję, np. dodać constructor promotion czy zamienić
switchnamatch. - Włącz wszystkie ostrzeżenia (
error_reporting(E_ALL)) i przejrzyj logi pod kątem komunikatów o przestarzałych elementach (Deprecated). - Przetestuj. Bez testów automatycznych aktualizacja jest loterią, więc to dobry moment, żeby je dopisać.
Uwaga mentora: przy aktualizacji starych projektów najczęściej zaczynamy od włączenia E_ALL i przejrzenia ostrzeżeń Deprecated. To pokazuje problemy, zanim zamienią się w wyjątki w kolejnej wersji.
Jakie błędy najczęściej pojawiają się po aktualizacji do PHP 8?
| Objaw | Przyczyna | Co zrobić |
|---|---|---|
Deprecated: Creation of dynamic property (8.2+) | przypisanie do właściwości, której klasa nie deklaruje | zadeklaruj właściwość albo oznacz klasę #[\AllowDynamicProperties] |
TypeError: Unsupported operand types | PHP 8 rzuca wyjątek tam, gdzie wcześniej było ostrzeżenie (np. "abc" * 2) | sprawdzaj i rzutuj dane wejściowe przed obliczeniami |
Deprecated: Passing null to parameter (8.1+) | null przekazany do funkcji wbudowanej, która oczekuje tekstu (np. strlen(null)) | pilnuj typów albo użyj ?? '' |
inne wyniki porównań == | zmiana porównywania liczby z tekstem | użyj === |
ArgumentCountError przy nazwanych argumentach | nazwa parametru w bibliotece ≠ używana w kodzie | użyj aktualnych nazw z dokumentacji pakietu |
Implicit conversion from float to int loses precision (8.1+) | float użyty jako indeks tablicy | rzutuj jawnie: (int) $x albo intdiv() |
Którą wersję PHP wybrać w nowym projekcie?
Dla nowego projektu wybierz najnowszą stabilną wersję, czyli dziś 8.5, a przy ograniczeniach hostingu 8.4. Obie mają wsparcie bezpieczeństwa na kolejne lata. Jeśli utrzymujesz stary projekt na 8.1 lub starszym, zaplanuj aktualizację teraz, bo takie wersje nie dostają już poprawek bezpieczeństwa.
Jeśli uczysz się PHP, nie musisz znać wszystkich zmian na pamięć. Wystarczy rozumieć match, typy, enumy, readonly i atrybuty, bo to z nich korzystają frameworki takie jak Laravel. Tego uczymy w ścieżce PHP z mentorem, na prawdziwych projektach, nie tylko na przykładach z dokumentacji.


