Migracja PHP ze starej wersji na aktualną (8.3+) to jedna z najbardziej opłacalnych modernizacji w starym systemie — usuwa całą klasę ryzyk bezpieczeństwa, przyspiesza aplikację bez zmian w kodzie biznesowym i odblokowuje aktualizacje frameworków oraz bibliotek. PHP 5.6 nie ma wsparcia bezpieczeństwa od końca 2018 roku, a wsparcie PHP 7 zakończyło się w 2022 — systemy działające na tych wersjach są dziś bez łat na znane podatności. Ten przewodnik pokazuje, jak zaplanować migrację krok po kroku i czego się spodziewać.
Najważniejsze: Migracja PHP to proces, nie podmiana wersji na serwerze. Kolejność: audyt zgodności (PHPCompatibility, PHPStan) → testy zabezpieczające → automatyczna refaktoryzacja (Rector) → staging → produkcja z monitoringiem. Bezpieczna migracja przez wersję pośrednią (np. 7.4) jest szybsza niż skok przez dwie generacje, choć w prostych projektach możliwy jest skok bezpośredni.
Dlaczego stara wersja PHP to problem
Trzy koszty, które rosną z każdym rokiem
Bezpieczeństwo. Wersje PHP po zakończeniu wsparcia nie dostają poprawek bezpieczeństwa. To nie teoretyczne ryzyko — znane podatności w interpreterze i bibliotekach standardowych zostają publicznie udokumentowane, a działający system staje się celem. W systemach obsługujących płatności czy dane osobowe to ryzyko compliance, nie tylko techniczne.
Kompatybilność ekosystemu. Nowe wersje bibliotek i frameworków wymagają nowych wersji PHP. Zostając na 5.6 czy 7.x, tracisz dostęp do aktualizacji, a wraz z nimi do poprawek bezpieczeństwa i wydajności. Coraz częściej także hostingi wygaszają obsługę starych wersji — musisz płacić za „dodatki legacy" albo szukać specjalnych rozwiązań.
Wydajność i koszty utrzymania. PHP 8.x jest istotnie szybsze od PHP 5.6 — sam JIT i optymalizacje silnika potrafią przyspieszyć aplikację o dziesiątki procent bez zmian w kodzie. Do tego dochodzi koszt ludzi: programistów znających PHP 5.6 jest coraz mniej, a stawki rosną. Szeroki kontekst tych kosztów rozkładam w artykule o długu technologicznym.
Jak wygląda droga migracji
Najbezpieczniejsza ścieżka z PHP 5.6 prowadzi przez wersję pośrednią — 7.4 albo 8.0 — i dopiero potem na 8.3+. Skok przez dwie generacje naraz jest możliwy, ale zwykle oznacza więcej błędów naraz i trudniejszą diagnozę. Wersja pośrednia daje punkty kontrolne: po każdym kroku testy, wdrożenie, obserwacja.
Dla aplikacji na Laravel dochodzi osobny wymiar — migracja frameworka między wersjami, z własną kolejnością i pułapkami. Opisuję ją w artykule o aktualizacji Laravel krok po kroku. Migracja PHP i migracja frameworka mogą iść razem, ale wtedy plan musi być tym bardziej ostrożny.
Krok 1 — audyt zgodności
Zanim zmienisz cokolwiek, zmierz skalę problemu. Narzędzia do zgodności wersji pokazują dokładnie, które fragmenty kodu przestaną działać:
- PHPCompatibility — ruleset dla PHP_CodeSniffer, który skanuje kod pod kątem konstrukcji usuniętych albo zmienionych w nowych wersjach,
- PHPStan z regułami dla docelowej wersji — wychwytuje problemy typów i wywołań, które w nowej wersji staną się błędami,
- lista rozszerzeń — czy system korzysta z rozszerzeń, które zniknęły albo zmieniły API (np.
mysql_*usunięte w PHP 7), - zależności — sprawdzenie, które biblioteki mają wersje kompatybilne z docelowym PHP, a które są porzucone.
Wynik audytu to lista blokad podzielona na kategorie: „do automatycznej naprawy", „do ręcznej decyzji", „do wymiany biblioteki". To jednocześnie plan migracji. Szerzej o tym etapie piszę w przewodniku o audycie kodu legacy.
Krok 2 — testy zabezpieczające
Migracja wersji PHP zmienia zachowanie systemu w miejscach, których nikt się nie spodziewa — od obsługi typów, przez sortowanie, po formatowanie liczb. Bez testów każdy taki efekt zobaczysz na produkcji.
Minimum to testy charakterystyczne na ścieżkach krytycznych: logowanie, zamówienie, płatność, generowanie dokumentów. Technikę ich pisania w starym kodzie opisuję w artykule o testach charakterystycznych. Testy uruchamiane w CI na docelowej wersji PHP zamieniają migrację z hazardu w proces z jasnymi kryteriami — zielone testy to warunek wdrożenia.
Krok 3 — automatyczna refaktoryzacja z Rector
Ręczne poprawianie kodu pod nową wersję PHP to tygodnie pracy. Rector robi to automatycznie: ma gotowe rulesety dla przejść między wersjami (PHP 5.6 → 7.x → 8.x), które podmieniają usunięte funkcje, aktualizują składnię i modernizują konstrukcje do aktualnych standardów.
Praktyka wdrożenia wygląda tak: uruchamiasz Rector z rulesetem dla najbliższego kroku, przeglądasz diff (mogą to być tysiące zmian — dlatego potrzebujesz testów), uruchamiasz testy, commitujesz. Kroki robisz wersja po wersji, a nie wszystko naraz — łatwiej wtedy przypisać ewentualne błędy do konkretnej zmiany.
Rector nie naprawi wszystkiego — logika oparta na zachowaniach, które zmieniły się między wersjami (np. rzutowanie typów, funkcje sortujące), wymaga decyzji człowieka. Ale eliminuje 80–90% mechanicznej pracy. Techniki refaktoryzacji, które warto połączyć z migracją, opisuję w artykule o refaktoryzacji legacy code.
Krok 4 — staging i wdrożenie
Migrację wdrażasz tak samo jak każdą inną zmianę w procesie modernizacji: najpierw środowisko staging z realnymi danymi (na kopii), potem produkcja z monitoringiem.
- staging powinien działać na docelowej wersji PHP z tymi samymi rozszerzeniami co produkcja — różnice w konfiguracji to najczęstsze źródło „u mnie działa",
- wdrożenie produkcyjne rób poza szczytem ruchu i miej plan wycofania — stara wersja PHP zostaje na serwerze do czasu potwierdzenia stabilności,
- po wdrożeniu obserwuj logi błędów i wydajność przez kilka dni; deprecation warnings w logach to lista rzeczy do posprzątania w kolejnych iteracjach,
- dopiero po stabilizacji zaktualizuj zależności i framework do wersji docelowych — to drugi etap tej samej podróży.
Automatyzacja wdrożeń i testów na każdym etapie to nie luksus, lecz warunek bezpiecznej migracji — konfigurację opisuję w artykule o CI/CD i DevOps dla Laravel.
Co się najczęściej psuje przy migracji
Doświadczenie z projektów mówi, że problemy skupiają się w kilku miejscach
- funkcje usunięte między wersjami —
each(),create_function(), rozszerzeniemysql_*, stare APIpreg_replacez modifierem/e, - typy i rzutowanie — nowe wersje są surowsze; kod, który „przechodził", teraz rzuca błędami typów,
- null i puste wartości — przekazywanie null do funkcji oczekujących stringów to deprecation w 8.1 i błąd w przyszłych wersjach,
- dynamiczne właściwości — tworzenie właściwości „w locie" jest deprecjonowane od 8.2; kod, który na tym polega, wymaga refaktoryzacji,
- biblioteki porzucone — zależność, która nie ma wersji kompatybilnej z PHP 8, wymaga zamiany (to najczęściej najbardziej czasochłonny punkt migracji),
- zachowania brzegowe — sortowanie, porównywanie stringów numerycznych, formatowanie — miejsca, gdzie zmiany semantyki języka widać dopiero w testach.
Żaden z tych punktów nie jest blokadą — każdy jest pozycją w planie. Groźne są tylko te, o których nie wiesz, że istnieją, dlatego audyt zgodności i testy są nie do pominięcia.
Ile to trwa i ile kosztuje
Mały projekt (kilkanaście tysięcy linii, brak egzotycznych zależności) przechodzi migrację w kilka dni. Średni system z frameworkiem i rozbudowanymi integracjami to typowo 2–8 tygodni, zależnie od liczby blokad i jakości testów. Największym zmiennym kosztem jest wymiana porzuconych bibliotek.
Migrację PHP warto zaplanować jako część szerszego programu modernizacji — wtedy koszty rozkładają się na etapy, a każdy z nich dostarcza wartość: bezpieczeństwo, wydajność, nowsze biblioteki. Widełki całego programu i punkt startowy (audyt za 2 000 zł netto) opisuję w artykule o kosztach modernizacji legacy, a zakres usługi na stronie modernizacji legacy PHP. Cały plan działania — od audytu po CI/CD — w pillarze o modernizacji legacy code.
Najczęściej zadawane pytania
Czy mogę zaktualizować PHP bez zmian w kodzie?
W prostych projektach czasem wystarczy aktualizacja i testy, ale to wyjątek. Kod pisany pod PHP 5.6 czy 7.x zwykle korzysta z konstrukcji usuniętych albo zmienionych w nowszych wersjach. Standardowa ścieżka to audyt zgodności, refaktoryzacja z Rector i testy — dopiero potem wdrożenie.
Czy migracja PHP wymaga zatrzymania systemu?
Nie. Migrację przygotowujesz na stagingu, a wdrożenie robisz jak każdą inną zmianę — poza szczytem, z możliwością wycofania. System nie musi być zatrzymywany na czas migracji; cała praca dzieje się poza produkcją, a na produkcji następuje tylko podmiana wersji.
Od której wersji PHP zaczynać, jeśli system działa na 5.6?
Bezpieczna droga wiedzie przez wersję pośrednią — najczęściej 7.4 — potem 8.0/8.1 i docelowo 8.3 lub nowszą. Wersje pośrednie dają punkty kontrolne: po każdym kroku uruchamiasz testy i wdrażasz. Skok bezpośredni jest możliwy w prostych projektach, ale utrudnia diagnozę błędów.
Czy aktualizacja PHP przyspieszy aplikację?
Zwykle tak, i to bez zmian w kodzie — nowsze wersje PHP są istotnie szybsze (optymalizacje silnika, JIT od 8.0). Realny zysk zależy od profilu aplikacji, ale przyspieszenie o kilkanaście–kilkadziesiąt procent nie jest rzadkością. Pełny efekt wydajnościowy wymaga też aktualizacji zależności i frameworka.