PHP 7 (od 7.0 z grudnia 2015 do 7.4 z listopada 2019) to wersja, która według zespołu PHP była około dwa razy szybsza od PHP 5.6. Dodała typy skalarne i typy zwracane, operatory??i<=>, wyjątkiError, a w wersji 7.4 typowane właściwości i funkcje strzałkowe. Dziś żadna wersja 7.x nie dostaje już poprawek bezpieczeństwa, więc nowe projekty powinny używać PHP 8.
PHP 7 to wersja, po której PHP przestał być „tym językiem, w którym wszystko jest luźno typowane i wolne”. Szóstki nie było: projekt z pełnym Unicode porzucono, a kolejnej wersji po 5.6 nadano numer 7. Poniżej omawiamy, co przyniosły kolejne wydania 7.0–7.4, jak mają się do PHP 5 i co jest dla Ciebie ważne, jeśli utrzymujesz stary kod. O tym, co działo się dalej, piszemy w artykule o nowościach i zmianach w PHP 8. Przykłady uruchomiliśmy w PHP 8.4.5, bo działają tak samo jak w siódemce, ale nie testowaliśmy ich na PHP 7.
Które wersje PHP 7 istniały i do kiedy były wspierane?
Wszystkie wersje 7.x są dziś nieobsługiwane. Według php.net:
| Wersja | Premiera | Koniec wsparcia bezpieczeństwa |
|---|---|---|
| 7.0 | 3 grudnia 2015 | 10 stycznia 2019 |
| 7.1 | 1 grudnia 2016 | 1 grudnia 2019 |
| 7.2 | 30 listopada 2017 | 30 listopada 2020 |
| 7.3 | 6 grudnia 2018 | 6 grudnia 2021 |
| 7.4 | 28 listopada 2019 | 28 listopada 2022 |
Jeśli Twoja aplikacja nadal działa na którejkolwiek z tych wersji, nie dostaje poprawek bezpieczeństwa. Dlatego warto zaplanować aktualizację.
Dlaczego PHP 7 był szybszy od PHP 5?
Zespół PHP przepisał rdzeń silnika (projekt nazywano wtedy PHPNG, a wynik to Zend Engine 3) tak, żeby mniej pamięci zużywały zmienne i tablice. Według oficjalnych benchmarków zespołu PHP 7.0 był około dwa razy szybszy od PHP 5.6 i potrzebował znacznie mniej pamięci. Tej liczby nie sprawdzaliśmy samodzielnie, więc traktuj ją jako deklarację zespołu. W praktyce zysk zależy od aplikacji: bardziej widać go w kodzie, który dużo działa na tablicach i obiektach, mniej tam, gdzie wszystko wisi na bazie danych.
To był największy jednorazowy skok wydajności w historii PHP. Kolejne wersje, łącznie z 8.x, dawały już mniejsze, stopniowe poprawki.
Co przyniosło PHP 7.0?
Jak działają typy skalarne i typy zwracane?
Od PHP 7.0 możesz deklarować int, float, string i bool w parametrach oraz typ zwracanej wartości. Domyślnie PHP próbuje przekonwertować argument, np. "5" na 5. Po dodaniu declare(strict_types=1); na początku pliku konwersja jest wyłączona i niezgodny typ kończy się wyjątkiem TypeError.
declare(strict_types=1);
function add(int $a, int $b): int {
return $a + $b;
}
echo add(2, 3); // 5
// add("2", 3); // TypeError (w trybie strict_types)
Do czego służy operator null coalescing ??
Zwraca lewy operand, jeśli istnieje i nie jest null, a w przeciwnym razie prawy. Zastąpił zapis isset($x) ? $x : 'domyślna', który w starym PHP był wszędzie.
$name = $_GET['name'] ?? 'gość';
Co robi operator spaceship <=>?
Zwraca -1, 0 albo 1, zależnie od tego, czy lewa strona jest mniejsza, równa czy większa od prawej. Przydaje się w funkcjach sortujących:
echo 1 <=> 2; // -1
echo 'b' <=> 'a'; // 1
echo 2 <=> 2; // 0
Czym są wyjątki Error i interfejs Throwable?
W PHP 5 wiele błędów (np. wywołanie metody na null) kończyło skrypt fatalnym błędem, którego nie dało się złapać. W PHP 7 część z nich to wyjątki klasy Error, więc możesz je obsłużyć w try/catch. Exception i Error implementują wspólny interfejs Throwable, więc catch (Exception $e) nie złapie błędów typu. Do tego potrzeba Error albo Throwable.
try {
echo intdiv(1, 0);
} catch (Throwable $e) {
echo get_class($e); // DivisionByZeroError
}
Co jeszcze weszło w 7.0?
- Klasy anonimowe —
new class { ... }, wygodne w testach i przy jednorazowych obiektach. - Grupowy
use— kilka klas z jednej przestrzeni nazw w jednej instrukcji. - Usunięte rozszerzenie
mysql_*— kod ze starego PHP, który korzystał zmysql_connect, przestaje działać. Zastępują jemysqlii PDO (zob. niżej). - Funkcje
random_int()irandom_bytes()— bezpieczne generowanie liczb losowych.
Co przyniosły PHP 7.1, 7.2 i 7.3?
W 7.1 doszły typy dopuszczające null (?int), typ zwracany void, typ iterable, krótka składnia [] do rozpakowywania tablic oraz łapanie kilku wyjątków w jednym catch (catch (A | B $e)).
function find(?int $id): ?string {
return $id === null ? null : "user-$id";
}
['id' => $id, 'name' => $name] = ['id' => 1, 'name' => 'Ola'];
try {
// ...
} catch (InvalidArgumentException | RuntimeException $e) {
// jedna obsługa dla obu wyjątków
}
W 7.2 pojawił się typ object, a do bezpiecznego haszowania haseł doszedł algorytm Argon2. W 7.3 doszły m.in. elastyczna składnia heredoc, przecinek na końcu listy argumentów oraz funkcje array_key_first() i array_key_last().
Co przyniosło PHP 7.4?
Ostatnia wersja z serii 7 i ta, która najbardziej przypomina dzisiejszy PHP. Według oficjalnego ogłoszenia weszły w niej m.in. typowane właściwości, funkcje strzałkowe, rozpakowywanie tablic i separator w literałach liczbowych.
Czym są typowane właściwości?
Właściwość klasy możesz teraz opatrzyć typem, a PHP pilnuje, żeby nie trafiła tam niezgodna wartość. Odczyt właściwości, która nie została jeszcze zainicjowana, rzuca błąd.
class Product {
public int $id;
public ?string $title = null;
}
$p = new Product();
// echo $p->id; // Error: właściwość nie została zainicjowana
// $p->id = "abc"; // TypeError: oczekiwano int
Jak działają funkcje strzałkowe?
Skracają jednolinijkowe domknięcia i automatycznie widzą zmienne z zewnętrznego zakresu (bez use).
$prices = [10, 20, 30];
$tax = 1.23;
$gross = array_map(fn($x) => $x * $tax, $prices);
Co jeszcze weszło w 7.4?
- Operator przypisania
??=—$cfg['a'] ??= 5;ustawia wartość tylko wtedy, gdy klucza nie ma albo jestnull. - Rozpakowywanie w tablicach —
[0, ...$a, 3]. - Separator liczb —
1_000_000zamiast1000000. - Preloading OPcache — ładowanie wybranych klas do pamięci przy starcie serwera.
Co zmieniło się względem PHP 5?
Jeśli ktoś pyta o różnicę między „starym” a „nowym” PHP, dobrze zacząć od poniższych punktów:
| Obszar | PHP 5.x | PHP 7.x |
|---|---|---|
| Typy | tylko klasy, array i callable w parametrach | dodatkowo int, float, string, bool i typy zwracane |
| Błędy | wiele błędów fatalnych bez możliwości obsługi | wyjątki Error i Throwable |
| Bazy danych | mysql_* | rozszerzenie mysql_* usunięte, zostają mysqli i PDO |
| Wydajność | punkt odniesienia | według zespołu PHP około dwa razy szybszy (7.0) |
| Zapis | isset($x) ? $x : 'a' | $x ?? 'a' |
Jak przejść z PHP 5 lub 7 na nowszą wersję?
Najczęstszy kłopot to kod ze starego PHP, który korzysta z usuniętych funkcji. Na Stack Overflow jednym z najczęściej oglądanych pytań w tym obszarze jest właśnie błąd po usunięciu mysql_connect (ponad 46 tys. wyświetleń).
- Zamień
mysql_*na PDO lubmysqli. PDO obsługuje zapytania przygotowane, które chronią przed SQL injection. - Uruchom statyczną analizę. PHPStan lub Psalm wskażą wywołania usuniętych funkcji i niezgodności typów.
- Wprowadź typy stopniowo. Zacznij od nowych plików, a
declare(strict_types=1)dodawaj tam, gdzie jesteś w stanie przetestować skutki. - Przeskocz na aktualną wersję, ale nie od razu na produkcji. Zaktualizuj środowisko testowe i przejrzyj logi.
Uwaga mentora: kod z PHP 5 poznasz po tym, że typy są w komentarzach (@param int $id), a nie w sygnaturze funkcji. Przy porządkowaniu takiego projektu zaczynamy od dodania typów w miejscach, gdzie dane wchodzą do systemu, czyli w kontrolerach i funkcjach pobierających dane z bazy, bo tam błędy typu najczęściej wychodzą na jaw.
Jeśli planujesz kolejny krok, czyli PHP 8, zajrzyj do artykułu o nowościach i zmianach w PHP 8. Jeśli uczysz się PHP od zera, nie zaczynaj od siódemki: zacznij od aktualnej wersji, a przy okazji rozmów rekrutacyjnych sprawdź pytania rekrutacyjne z PHP. Tego, jak pisać nowoczesny kod w PHP i Laravelu, uczymy w ścieżce PHP z mentorem.


