ix
ix

informatix

EN version Porozmawiajmy o projekcie
Usługi profesjonalne (anonimowo) Case study

Modernizacja aplikacji PHP

Jak krytyczny biznesowo system na PHP 5.6 — bez testów, bez kopii zapasowych, z ręcznymi wdrożeniami po FTP — stał się przetestowaną, skonteneryzowaną aplikacją PHP 8.4 z CI/CD i monitoringiem. Bez przepisywania od zera. Bez przestojów.

KS Krzysztof Słonina Opublikowano: Aktualizacja: 14 min czytania

Najważniejsze

System działał na PHP 5.6 — wersji bez wsparcia bezpieczeństwa od grudnia 2018 roku. Każda zmiana była loterią: brak testów, brak kopii zapasowych, wdrożenia ręcznie po FTP i krytyczne awarie, których nikt nie umiał wyjaśnić. Rozwiązaniem nie było przepisanie od zera, a modernizacja etapami: audyt kodu (PHPCompatibility, PHPStan, inwentarz zależności), siatka bezpieczeństwa z testów charakterystycznych, refaktoryzacja moduł po module z Rector, CI/CD z GitHub Actions i Docker oraz monitoring, który wykrywa problemy zanim zgłoszą je użytkownicy. Efekt: zero krytycznych awarii przez 12 miesięcy, wdrożenia skrócone z 2 tygodni do 2 dni, koszty utrzymania niższe o 60%.

Problem

Krytyczna biznesowo aplikacja zbudowana lata wcześniej na PHP 5.6: przez system codziennie przechodziły procesy klientów, rozliczenia i raportowanie. Kod nie miał testów, kopii zapasowych ani dokumentacji — wiedza o nim żyła w głowie jednego programisty. Wdrożenia odbywały się ręcznie, po FTP, w nocy, z duszą na ramieniu; pojedyncza zmiana zajmowała dwa tygodnie od decyzji do produkcji. Wersja PHP była po zakończeniu wsparcia od grudnia 2018 roku, co oznaczało znane luki bezpieczeństwa bez poprawek — a system przetwarzał dane osobowe, więc było to ryzyko zgodności z RODO, nie tylko techniczne. Każdą awarię diagnozowano z pamięci. Nikt nie mógł bezpiecznie stwierdzić, co się zepsuje po aktualizacji zależności, więc nic nie było aktualizowane. Klasyczny paraliż systemu legacy: koszt zmiany rośnie z każdym miesiącem nicnierobienia.

Rozwiązanie

Zmodernizowaliśmy aplikację etapami, zamiast przepisywać ją od zera. Najpierw audyt kodu: skany PHPCompatibility i PHPStan, pełny inwentarz zależności przez Composer i odkrycie środowiska uruchomieniowego (wersja PHP, rozszerzenia, php.ini, serwer webowy, baza danych). Potem siatka bezpieczeństwa: testy charakterystyczne w PHPUnit na wszystkich krytycznych ścieżkach biznesowych. Następnie refaktoryzacja moduł po module — rozliczenia, raportowanie, panel administracyjny, integracje — z Rector automatyzującym zmiany wersji (5.6 → 7.4 → 8.x) i wzorcem strangler fig, dzięki któremu stary i nowy kod działały równolegle. Każdy moduł przechodził przez staging, potem produkcję, z gotowym rollbackiem. Równolegle zastąpiliśmy FTP pipeline’em CI/CD: GitHub Actions uruchamiał testy, kontenery Docker czyniły staging identycznym z produkcją, a wdrożenia były monitorowane. Na tym doszedł monitoring — New Relic, śledzenie błędów i alerty z logów — żeby incydenty pojawiały się jako alerty, a nie jako skargi klientów. Stara wersja PHP została na serwerze do potwierdzenia stabilności. Zero przestojów przez cały program.

Efekt

Zero krytycznych awarii przez 12 miesięcy — po latach regularnych incydentów. Czas wdrożenia skrócony z 2 tygodni do 2 dni, co odblokowało backlog, o który biznes przestał już pytać. Koszty utrzymania niższe o 60%: zespół przestał płacić „premię legacy” programistom chętnym do pracy z PHP 5.6 i tracić dni na ręczne wdrożenia. Pokrycie testami krytycznych ścieżek: od zera do pełnego zestawu regresji działającego przy każdej zmianie. Kopie zapasowe z testowanym odtworzeniem zastąpiły zasadę „nikt nie dotyka serwera”. Monitoring wykrywa problemy w minutach, nie przez zgłoszenia użytkowników. I zniknęło ryzyko kluczowej osoby: środowisko uruchomieniowe jest udokumentowane, pipeline odtwarzalny, a każdy programista w zespole może bezpiecznie wdrażać zmiany. PHP 8.4 ma wsparcie do grudnia 2028 — następna aktualizacja to rutyna, nie projekt.

Wyniki przed i po

Wskaźnik Przed Po
Krytyczne awarie regularne, z awaryjnymi poprawkami zero — 12 miesięcy
Czas wdrożenia 2 tygodnie (ręcznie, FTP) 2 dni
Pokrycie testami krytycznych ścieżek brak testów pełny zestaw regresji w CI
Koszty utrzymania poziom bazowy −60%
Kopie zapasowe i rollback brak automatyczne, z testowanym odtworzeniem
Wykrywanie incydentów ze zgłoszeń użytkowników alerty monitoringu w minuty
Wersja PHP 5.6 — EOL od grudnia 2018 8.4 — wsparcie do grudnia 2028

Stack technologiczny przed i po

Obszar Przed Po
Wersja PHP PHP 5.6 — EOL od grudnia 2018 PHP 8.4 — wsparcie do grudnia 2028
Framework czysty PHP, bez frameworka Laravel na PHP 8.4
Testy brak testów PHPUnit — testy charakterystyczne i regresja w CI
Analiza statyczna brak PHPStan i PHPCompatibility w pipeline’ie
Wdrożenia ręcznie, po FTP, w nocy GitHub Actions — CI/CD z rollbackiem jedną komendą
Środowiska staging różny od produkcji Docker — identyczne kontenery
Baza danych i cache PostgreSQL bez warstwy cache PostgreSQL + Redis (cache, kolejki, sesje)
Monitoring brak — awarie ze zgłoszeń New Relic + alerty błędów i logów
Kopie zapasowe brak automatyczne, z testowanym odtworzeniem

Punkt wyjścia — krytyczny system, którego nikt nie mógł bezpiecznie zmieniać

Aplikacja działała na PHP 5.6 — wersji bez wsparcia bezpieczeństwa od grudnia 2018 roku. Codziennie przetwarzała dane klientów, rozliczenia i raporty, a mimo to nie miała testów, kopii zapasowych ani dokumentacji. Wdrożenia były ręczne, po FTP, po godzinach; pełny cykl od decyzji do produkcji zajmował około dwóch tygodni. Awarie zdarzały się regularnie i były diagnozowane z pamięci, bo nic nie rejestrowało faktycznego zachowania systemu. Zespół przestał prosić o zmiany — backlog pełen był funkcji, o które nikt nie śmiał się upomnieć. Tak wygląda dług techniczny, gdy dojrzeje: nie liczba w arkuszu, a biznes, który po cichu obchodzi własny system. Wątek zgodności czynił sprawę pilną: dane osobowe przetwarzane przez interpreter ze znanymi, niezałatanymi lukami to ekspozycja RODO, nie tylko niedogodność utrzymaniowa.

Dlaczego nie przepisaliśmy systemu od zera — czym naprawdę jest strategia modernizacji legacy

Odruch wobec kodu legacy to przepisanie od zera — i zwykle jest to najdroższy sposób na porażkę. Przepisanie oznacza odtworzenie lat nieudokumentowanych reguł biznesowych bez sposobu porównania nowego systemu ze starym, dopóki nie będzie za późno. Alternatywą jest strategia modernizacji: utrzymywać działanie systemu, poprawiając go weryfikowalnymi krokami. Najpierw audyt, potem siatka testów, refaktoryzacja inkrementalna, automatyzacja i monitoring. Każdy krok jest samodzielnie bezpieczny i sam w sobie daje wartość. Dokładnie tak przebiegał ten projekt — i tak działa każdy poradnik w naszym hubie modernizacji legacy. Kod legacy to zresztą nie „zły kod”: to działający kod napisany w przeszłości, noszący wartość biznesową, którą przepisanie stawiałoby na szali.

Krok 1 — audyt kodu: zmierzyć problem, zanim dotknie się czegokolwiek

Modernizacja zaczyna się od rozpoznania, nie od kodu. Przeskanowaliśmy kod narzędziem PHPCompatibility (konstrukcje usunięte lub zmienione w nowszych wersjach PHP), uruchomiliśmy PHPStan pod kątem błędów typów i wywołań, które stałyby się fatalne na docelowej wersji, i zinwentaryzowaliśmy każdą zależność przez Composer — oznaczając biblioteki porzucone, bez wydania zgodnego z PHP 8. Równolegle zmapowaliśmy środowisko uruchomieniowe: dokładną wersję PHP i rozszerzenia, ustawienia php.ini, serwer webowy (nginx), bazę danych (PostgreSQL) i użycie Redis. To odkrycie środowiska ma większe znaczenie, niż brzmi: różnice konfiguracji między środowiskami to najczęstsze źródło sytuacji „na stagingu działa, na produkcji padło”. Audyt dał listę blokerów w trzech kategoriach — do naprawy automatycznej, wymagające decyzji człowieka, do wymiany biblioteki — która posłużyła jednocześnie jako plan migracji i podstawa wyceny. Ujawnił też lukę dokumentacyjną: krytyczna wiedza istniała tylko w głowie pierwotnego programisty. Zamknęliśmy ją ustrukturyzowanymi wywiadami i spisaną mapą środowiska.

Architektura modernizacji aplikacji PHP przed i po — od monolitu PHP 5.6 z ręcznymi wdrożeniami po FTP i bez testów, do modularnej aplikacji PHP 8.4 w kontenerach Docker z CI/CD GitHub Actions, testami regresji PHPUnit, cache Redis i monitoringiem New Relic
Architektura przed i po: ręczne wdrożenia po FTP i monolit PHP 5.6 zastąpione kontenerami, pipeline’em CI/CD, testami regresji i monitoringiem.

Krok 2 — testy charakterystyczne: siatka bezpieczeństwa przed pierwszą refaktoryzacją

Refaktoryzacja kodu bez testów to nie modernizacja — to hazard. Ale system legacy nie ma testów do uruchomienia, więc pierwsze zadanie testowe jest inne: testy charakterystyczne (technika opisana przez Michaela Feathersa) zapisują, co system faktycznie robi dziś — także zachowania wyglądające na błąd — dzięki czemu każda zmiana, która je modyfikuje, staje się natychmiast widoczna. Pokryliśmy najpierw krytyczne ścieżki biznesowe: logowanie, procesy klientów, rozliczenia, generowanie dokumentów i raportowanie — 15–20 testów end-to-end wyłapało zdecydowaną większość ryzyk. Działały w CI na docelowej wersji PHP od pierwszego dnia, co zamieniło aktualizację z aktu wiary w proces z jasnym kryterium akceptacji: zielone testy to warunek wdrożenia. Brak testu — brak wydania; sama ta zasada wyeliminowała model „dowiemy się od użytkowników”.

Krok 3 — refaktoryzacja moduł po module z Rector, zamiast przepisywania z rozmachem

Z siatką bezpieczeństwa w miejscu refaktoryzowaliśmy jeden moduł na raz: najpierw rozliczenia (najwyższe ryzyko), potem raportowanie, panel administracyjny i na końcu integracje. Rector wykonał pracę mechaniczną — jego zestawy reguł dla przejść między wersjami zautomatyzowały 80–90% zmian z PHP 5.6 przez 7.4 do 8.x: usunięte funkcje zastąpione, składnia zmodernizowana, przestarzałe konstrukcje wyeliminowane. Każde uruchomienie Rector przechodziło ten sam cykl: wygeneruj diff, przejrzyj, uruchom pełny zestaw testów, zatwierdź — wersja po wersji, żeby każdy błąd można było przypisać konkretnej zmianie. Porzucone biblioteki zastąpiliśmy utrzymywanymi alternatywami; tam, gdzie żadnej nie było, funkcjonalność przenieśliśmy do naszego kodu — najpierw z testami. Gdy moduł wymagał głębszej przebudowy, używaliśmy wzorca strangler fig: nowy kod rósł za tymi samymi interfejsami, a stara implementacja wciąż obsługiwała ruch — system nigdy nie był „w połowie migracji”, zawsze działał. Symfony rozważaliśmy wcześnie jako cel frameworkowy; pragmatycznym wyborem okazał się Laravel na PHP 8.4 — zgodny z umiejętnościami zespołu i istniejącą warstwą bazy danych.

Proces modernizacji moduł po module — audyt kodu z PHPStan i PHPCompatibility, testy charakterystyczne, refaktoryzacja z Rector modułów rozliczeń, raportowania, panelu administracyjnego i integracji, staging, wdrożenie produkcyjne i monitoring
Strangler fig w praktyce: każdy moduł (rozliczenia, raportowanie, panel admina, integracje) przechodził audyt, testy, refaktoryzację, staging i monitoring — bez wielkiej rewolucji.

Krok 4 — z FTP do CI/CD: GitHub Actions, Docker i wdrożenia odwracalne

Proces wdrożeniowy był drugą główną przyczyną awarii, więc dostał takie samo leczenie jak kod. Zbudowaliśmy pipeline w GitHub Actions: każdy push uruchamia zestaw PHPUnit, analizę statyczną i build; scalenia do main wdrażają na staging automatycznie, a wydania produkcyjne to monitorowana operacja jedną komendą. Kontenery Docker czynią staging i produkcję naprawdę identycznymi — ta sama wersja PHP, te same rozszerzenia, ta sama konfiguracja — co wyeliminowało całą klasę błędów środowiskowych. Każde wydanie ma ścieżkę rollbacku: poprzedni obraz pozostaje dostępny, migracje bazy piszemy tak, by były zgodne wstecz przez jedno wydanie, a stara wersja PHP została na serwerze do potwierdzenia stabilności. Czas wdrożenia spadł z dwóch tygodni do dwóch dni, a — co ważniejsze — wdrożenia przestały być wydarzeniami. Jenkins i Ansible były na stole; dla projektu tej skali GitHub Actions z Dockerem okazał się kombinacją pragmatyczną, z najmniejszą liczbą ruchomych części do utrzymania.

Krok 5 — monitoring: incydenty mają być alertami, nie skargami

Aplikacja bez monitoringu to system, o którego awariach dowiadujesz się od klientów. Wyposażyliśmy aplikację w New Relic (czasy odpowiedzi, wolne zapytania, wskaźniki błędów), dodaliśmy śledzenie błędów i alerty z logów oraz progi na metrykach, które liczą się dla biznesu: nieudane logowania, błędy na ścieżce płatności, głębokość kolejek w Redis, czasy odpowiedzi bazy. Ostrzeżenia o przestarzałych konstrukcjach z PHP 8 stały się listą zadań zamiast szumem — każda pozycja to małe, zaplanowane porządki, a nie przyszła awaria. Pierwszy miesiąc alertów zwrócił koszt całej warstwy monitoringu: dwa wolne zapytania znaleziono i naprawiono, zanim zauważyli je użytkownicy. Wykrywanie incydentów przeniosło się z godzin (zgłoszenia) na minuty (alerty), a wraz z nim skrócił się czas usuwania skutków.

Wyzwania po drodze — czego nie widać w planie modernizacji

Każda modernizacja legacy napotyka wyzwania, których nie widać w żadnym planie. Pierwsze: porzucone biblioteki — kilka zależności nie miało wydania zgodnego z PHP 8 i żadnej aktywnej alternatywy, więc ich funkcjonalność trzeba było odtworzyć we własnym kodzie, z testami przed wdrożeniem. Drugie: nieudokumentowane reguły biznesowe — zachowania, które wyglądały na błędy, okazywały się wymaganiami; testy charakterystyczne zamroziły je jako kontrakt, zamiast „naprawiać” po cichu. Trzecie: ryzyko kluczowej osoby — wiedza o systemie mieszkała w jednej głowie, więc równolegle z refaktoryzacją prowadziliśmy wywiady i dokumentację. Czwarte: opór przed zmianą — zespół po latach awarii bał się każdego wdrożenia; dopiero pierwsze miesiące z zielonym pipeline’em i alertami zamiast telefonów od klientów odwróciły tę postawę. Piąte: różnice środowisk — „na stagingu działa” przestało być argumentem dopiero wtedy, gdy Docker uczynił środowiska identycznymi. Te wyzwania nie znikają w żadnej metodyce — różnica polega na tym, że modernizacja etapami czyni je widocznymi i rozwiązywalnymi pojedynczo, zamiast zostawiać je ukryte w wielkim przepisaniu.

Sama migracja PHP 5.6 → 8.4 — co się zepsuło i co zyskaliśmy

Ścieżka wersji prowadziła przez punkty kontrolne — 5.6 → 7.4 → 8.x — a nie jednym skokiem przez trzy generacje, więc każdy etap miał własny cykl testów i wdrożenie. Psuło się to, co z perspektywy czasu przewidywalne, a bez przygotowania drogie: usunięte funkcje (each(), create_function(), stare rozszerzenie mysql_*, modyfikator /e w preg_replace), surowsza obsługa typów, która ciche konwersje zamieniła w błędy, przekazywanie null do parametrów nienullowalnych (deprecated od 8.1) i dynamiczne właściwości (deprecated od 8.2), na których opierało się kilka starszych bibliotek. Testy charakterystyczne wyłapały każdy z tych przypadków przed produkcją. Zyski przyszły z 8.x: kompilacja JIT, atrybuty zamiast adnotacji, enumy, promocja właściwości konstruktora i właściwości readonly — oraz mierzalny wzrost wydajności samego interpretera, dziesiątki procent na najcięższych endpointach, bez dotykania logiki biznesowej. PHP 8.4 ma pełne wsparcie do grudnia 2028, a PHP 8.5 jest już dostępne — platforma jest teraz przed roadmapą, a nie lata za nią.

Wyniki modernizacji PHP przed i po — zero krytycznych awarii przez 12 miesięcy, czas wdrożenia z 2 tygodni do 2 dni, koszty utrzymania niższe o 60 procent, PHP 5.6 po EOL zastąpione PHP 8.4 ze wsparciem do 2028 roku
Metryki operacyjne przed i po programie — dane z anonimizowanego projektu, dwanaście miesięcy po wydaniu ostatniego modułu.

Zespół — usunięcie ryzyka kluczowej osoby i utrwalenie modernizacji

Technologia była połową tego projektu; drugą połową byli ludzie. Oryginalny system zależał od jednego programisty, który go rozumiał — ryzyko kluczowej osoby, które już raz wywołało kryzys, gdy był niedostępny. Udokumentowaliśmy środowisko uruchomieniowe, spisaliśmy procedury wdrożeń i rollbacku, a przez cały czas pracowaliśmy w parach z zespołem klienta: programiści i administratorzy przechodzili przez ten sam pipeline, zamykając lukę, o którą chodzi w kulturze DevOps. Pod koniec programista klienta sam wdrażał przez pipeline, czytał alerty i planował kolejne aktualizacje modułów. Modernizacja, która zostawia zespół w tyle, nie jest skończona — przekazanie wiedzy było częścią kryteriów odbioru, nie dodatkiem.

Wyniki — przed i po, z liczbami

Dwanaście miesięcy po wydaniu ostatniego modułu: zero krytycznych awarii wobec wcześniejszych regularnych incydentów z awaryjnymi poprawkami. Czas wdrożenia skrócony z 2 tygodni do 2 dni; częstotliwość wydań wzrosła z „tylko gdy trzeba” do kilku wdrożeń w miesiącu. Koszty utrzymania niższe o 60% — zniknęła premia za umiejętności PHP 5.6 i ręczne rytuały wydawnicze. Kopie zapasowe działają automatycznie, z testowanym odtworzeniem; monitoring wykrywa anomalie w minutach. Zestaw testów, który zaczął się od 15–20 testów charakterystycznych, pilnuje dziś każdej krytycznej ścieżki — i to dzięki niemu aktualizacje zależności, wcześniej niemożliwe, są teraz rutynowym zadaniem. Tabela metryk powyżej zbiera dane przed/po z anonimizowanego projektu. Najważniejszej liczby nie ma w tabeli: backlog, o który biznes przestał pytać, znowu się rusza.

Wyniki biznesowe — wydajność, skalowalność, niezawodność i doświadczenie użytkownika

Metryki techniczne przekładają się na język biznesu. Wydajność: JIT i OPcache w PHP 8.x plus naprawa dwóch wolnych zapytań dały dziesiątki procent szybsze najcięższe ekrany — bez zmiany logiki biznesowej. Skalowalność: kontenery Docker i kolejki Redis pozwalają skalować aplikację poziomo wtedy, gdy rośnie ruch, zamiast wymieniać serwer „na większy”. Niezawodność: zero krytycznych awarii przez 12 miesięcy to nie tylko brak strat wizerunkowych — to również koniec nadgodzin przy awaryjnych poprawkach i przewidywalny SLA dla klientów końcowych. Doświadczenie użytkownika: modernizacja odbyła się przy zachowaniu pełnej zgodności funkcji (feature parity) — użytkownicy nie zobaczyli migracji, a zaczęli odczuwać szybsze działanie systemu; formularze i raporty odpowiadają zauważalnie szybciej. Wzrost: odmrożony backlog oznacza nowe funkcje i nowe przychody zamiast kolejnego roku utrzymywania status quo. Modernizacja legacy to zatem nie projekt techniczny — to inwestycja we wzrost: koszty utrzymania niższe o 60%, wdrożenia z 2 tygodni do 2 dni i platforma gotowa na kolejne lata rozwoju.

Kiedy modernizacja się opłaca — i jak zacząć

Sygnały są spójne w projektach legacy: wersja PHP po zakończeniu wsparcia, brak testów, ręczne wdrożenia, awarie diagnozowane z pamięci i wiedza skupiona w jednej osobie. Każde dwa z nich oznaczają, że koszt nicnierobienia już narasta — utrzymanie systemu legacy kosztuje zwykle 2–3 razy więcej niż jego nowoczesny odpowiednik, jeszcze przed doliczeniem ryzyka bezpieczeństwa i zgodności. Modernizacja opłaca się, gdy koszt nicnierobienia przewyższa koszt pracy; dla systemów takich jak w tym case study ten punkt minęliśmy dawno. Pierwszy krok jest zawsze ten sam i zawsze tani względem problemu: audyt kodu, który daje listę blokerów, mapę ryzyk i plan etapowy z wyceną. Typowe skale: mały projekt (kilkanaście tysięcy linii) modernizuje się w dni do tygodni; średni system z frameworkiem i integracjami — 2–8 tygodni; duże systemy bez testów — etapami przez kilka miesięcy. Jeśli rozpoznajesz swój system w tym case study, zacznij od audytu — wszystko dalej to decyzje podejmowane z danymi w ręku.

Wnioski

Trzy wnioski z tego projektu, w kolejności ważności. Po pierwsze: testy przed refaktoryzacją, zawsze — testy charakterystyczne to różnica między modernizacją a hazardem i najtańsze ubezpieczenie całego programu. Po drugie: moduł po module bije wielką rewolucję — każdy moduł wdrażał się i stabilizował osobno, system nigdy nie stanął, a biznes widział postęp od pierwszego miesiąca zamiast czekać rok na przepisanie. Po trzecie: monitoring od pierwszego dnia — warstwa obserwowalności zwróciła się w pierwszym miesiącu i to ona czyni pozostałe dwa wnioski weryfikowalnymi na produkcji, a nie na tablicy.

Najczęściej zadawane pytania

Czy można zmodernizować aplikację PHP bez przepisywania jej od zera?

W zdecydowanej większości przypadków tak — a przepisanie od zera jest zwykle opcją bardziej ryzykowną. Nowoczesne podejście jest inkrementalne: audyt kodu, siatka bezpieczeństwa z testów charakterystycznych, potem refaktoryzacja moduł po module (rozliczenia, raportowanie, panel administracyjny, integracje) ze wzorcem strangler fig, w którym nowy kod działa obok starego, aż moduł zostanie w pełni zastąpiony. Ten case study to dokładnie taka ścieżka — bez wielkiego wydania, bez przestojów i bez przepisywania całego systemu. Pełne przepisanie ma sens tylko wtedy, gdy same reguły biznesowe zmieniły się nie do poznania albo platforma docelowa jest fundamentalnie inna.

Ile trwa modernizacja aplikacji PHP?

Skala zależy od stanu kodu, nie od jego wieku. Mały projekt (kilkanaście tysięcy linii, bez egzotycznych zależności) to dni do tygodni. Średni system z frameworkiem, integracjami i kilkoma porzuconymi bibliotekami — jak w tym case study — to 2–8 tygodni aktywnej pracy, zwykle rozłożonej na etapowe wydania. Duże systemy legacy bez testów modernizuje się etapami przez kilka miesięcy. To audyt zamienia te widełki w konkretną wycenę dla Twojego systemu: daje listę blokerów i plan etapowy, na którym można oprzeć budżet.

Ile kosztuje modernizacja aplikacji PHP?

Typowe widełki: 3 000–10 000 zł dla małego projektu, 10 000–40 000 zł dla średniego systemu z frameworkiem i integracjami oraz od 40 000 zł w górę dla dużych systemów legacy, rozliczanych etapami. Dwie największe zmienne kosztowe to porzucone biblioteki (jedna zależność bez wydania na PHP 8 może pochłonąć tydzień) oraz stan testów (projekt bez testów wymaga zbudowania siatki bezpieczeństwa — często to największa pojedyncza pozycja). Stałą wycenę przygotowujemy po bezpłatnym audycie lub analizie zakresu.

Czy PHP to nadal dobry wybór w 2026 — czy PHP się kończy?

PHP napędza większość stron z rozpoznanym językiem serwerowym — ponad 70% według szacunków W3Techs — a sam język nigdy nie był szybszy: PHP 8.x przyniósł kompilację JIT i nowoczesne mechanizmy (atrybuty, enumy, właściwości readonly, property hooks w 8.4). Realne pytanie nie brzmi „PHP czy coś innego”, tylko „wspierane PHP czy PHP po EOL”. PHP 8.4 ma pełne wsparcie do grudnia 2028, a 8.5 jest już dostępne. Frameworki Laravel i Symfony wydają aktualne, utrzymywane wersje. Wymiana PHP ma sens dla zadań, w których nigdy nie był dobry (ciężkie obliczenia CPU), a nie dla typowych aplikacji webowych, które potrzebują po prostu aktualnej wersji i zmodernizowanego kodu.

Czym jest strategia modernizacji legacy?

Strategia modernizacji legacy to etapowy plan ulepszania starego systemu, gdy ten cały czas działa, zamiast wymiany w jednym ryzykownym ruchu. Sekwencja, która sprawdza się w praktyce: (1) audyt kodu — skany zgodności, analiza statyczna i inwentarz zależności dają listę blokerów; (2) siatka bezpieczeństwa — testy charakterystyczne zapisują obecne zachowanie; (3) refaktoryzacja inkrementalna — moduł po module, z automatyzacją (Rector) i wzorcem strangler fig; (4) CI/CD i kontenery — wdrożenia stają się automatyczne i odwracalne; (5) monitoring — incydenty pojawiają się jako alerty. Każdy krok jest samodzielnie bezpieczny i daje wartość — dlatego to podejście konsekwentnie wygrywa z przepisywaniem od zera.

Czy trzeba zatrzymać system na czas migracji?

Nie. W tym projekcie aplikacja nie zatrzymała się ani na chwilę — ani podczas migracji wersji PHP, ani podczas refaktoryzacji modułów. Metoda: cała praca odbywa się na stagingu z kopiami danych, wydania produkcyjne planujemy poza szczytem ruchu, migracje bazy piszemy tak, by były zgodne wstecz przez jedno wydanie, a poprzednia wersja pozostaje gotowa do rollbacku. Użytkownik widzi rutynowe wydanie, nie migrację. Jeśli wykonawca twierdzi, że migracja wymaga przestoju, to sygnał o metodzie, nie prawo natury.

Na jaką wersję PHP migrować — i co z końcem wsparcia PHP 8.2?

Celuj w PHP 8.4 (pełne wsparcie do grudnia 2028) lub 8.5 — aktualne stabilne gałęzie. Dwa terminy czynią sprawę pilną w 2026: PHP 8.2 kończy wsparcie 31 grudnia 2026, a wszystko na 8.1 i starszych (w tym 5.6 i 7.x) jest już bez poprawek bezpieczeństwa. Jeśli migrujesz z 5.6 lub 7.x, nie zatrzymuj się na 8.0/8.1 — te wersje są po EOL. Bezpieczna ścieżka prowadzi przez wersję pośrednią (np. 7.4), potem do 8.4 — jest szybsza, niż brzmi, bo każdy krok jest mały i testowalny.

Czy działanie na PHP po zakończeniu wsparcia to realne ryzyko bezpieczeństwa?

Tak — a dla systemów przetwarzających dane osobowe to także ryzyko zgodności. Wersja PHP po EOL nie otrzymuje poprawek bezpieczeństwa: luki w interpreterze i bibliotekach standardowych są publicznie dokumentowane, a działający system staje się znanym celem. WAF czy reguły sieciowe zmniejszają ekspozycję, ale nie łatają interpretera. W kontekście RODO przetwarzanie danych osobowych z niezałatanymi, publicznie znanymi lukami jest trudne do obrony w przeglądzie incydentu. Sama migracja — jak pokazuje ten case study — może przebiegać bez przestojów, więc „nie stać nas na ryzyko migracji” odwraca rzeczywisty profil ryzyka.

Od czego zacząć — co obejmuje audyt?

Audyt to najtańszy etap programu o największej dźwigni. Obejmuje: skan PHPCompatibility na docelową wersję (co się zepsuje), analizę statyczną PHPStan (błędy typów i wywołań), pełny inwentarz zależności przez Composer (które biblioteki wspierają docelowe PHP, które są porzucone) oraz odkrycie środowiska uruchomieniowego (wersja PHP i rozszerzenia, php.ini, serwer webowy, baza, cache). Wynik to lista blokerów podzielona na pozycje automatyczne, wymagające decyzji i do wymiany bibliotek — jednocześnie plan migracji, mapa ryzyk i podstawa stałej wyceny. Większość audytów zajmuje dni, nie tygodnie.

Jakie narzędzie przyspiesza modernizację legacy?

W praktyce modernizację przyspiesza zestaw narzędzi, nie jedno. Rector wykonuje automatyczną migrację składni między wersjami PHP — w tym projekcie zautomatyzował 80–90% mechanicznych zmian (5.6 → 7.4 → 8.x). PHPCompatibility skanuje kod pod kątem konstrukcji niekompatybilnych z docelową wersją, a PHPStan wyłapuje błędy typów i wywołań, zanim staną się fatalne. Testy charakterystyczne (PHPUnit) zamrażają obecne zachowanie systemu, dzięki czemu każdą zmianę można bezpiecznie weryfikować. GitHub Actions automatyzuje cały cykl: testy, analizę i wdrożenie. To połączenie — Rector + PHPCompatibility + PHPStan + testy w CI — skraca modernizację z miesięcy do tygodni.

Czy możesz podać przykład modernizacji legacy?

Tak — ten case study jest właśnie takim przykładem. Krytyczny system na PHP 5.6 (po EOL od 2018, bez testów, z wdrożeniami po FTP) przeszedł pełną modernizację: audyt, testy charakterystyczne, refaktoryzację modułową z Rector, CI/CD i monitoring. Efekt po 12 miesiącach: zero krytycznych awarii, wdrożenia z 2 tygodni do 2 dni, koszty utrzymania niższe o 60%. Kolejne przykłady i pełny plan działania opisujemy w hubie modernizacji legacy.

Jak zmodernizować aplikację legacy krok po kroku?

Sprawdzona sekwencja: (1) audyt kodu — PHPCompatibility, PHPStan, inwentarz zależności i mapowanie środowiska; (2) testy charakterystyczne na krytycznych ścieżkach biznesowych; (3) refaktoryzacja moduł po module z Rector i wzorcem strangler fig; (4) CI/CD i kontenery — wdrożenia automatyczne i odwracalne; (5) monitoring — alerty zamiast zgłoszeń od użytkowników. Każdy krok jest samodzielnie bezpieczny, a system cały czas działa — dokładnie tak przebiegał projekt w tym case study.

Czym zastępuje się PHP?

Rzadko czymkolwiek — i zwykle nie powinno się. PHP napędza ponad 70% stron z rozpoznanym językiem serwerowym (W3Techs), a nowoczesne wersje 8.x są szybkie i aktywnie rozwijane. Realne scenariusze wymiany to wąskie przypadki: ciężkie obliczenia CPU (Python, Go), aplikacje real-time (Node.js, Elixir) albo systemy, w których zespół już pracuje w innym ekosystemie (Java, C#). Dla typowych aplikacji webowych i e-commerce właściwą odpowiedzią nie jest zmiana języka, a aktualizacja do wspieranej wersji PHP i modernizacja kodu — migracja na inny stos zwykle mnoży koszty bez zysku biznesowego.

Czy ktoś jeszcze używa PHP?

Tak — i to zdecydowana większość webu. PHP działa na ponad 70% stron z rozpoznanym językiem serwerowym: WordPress, WooCommerce, PrestaShop, a w świecie aplikacji Laravel i Symfony. Ekosystem narzędzi (Composer, PHPStan, Rector, PHPUnit) jest dojrzały, a wydania 8.x wychodzą co roku. Pytanie „czy ktoś jeszcze używa PHP” zadają zwykle zespoły, które utknęły na wersji po EOL — problemem nie jest język, a nieaktualizowany kod.

Czy warto uczyć się PHP w 2026?

Tak, z jednym zastrzeżeniem: ucz się nowoczesnego PHP. Rynek pracy dla PHP jest nadal jednym z największych w web developmencie — utrzymanie i modernizacja istniejących systemów to stały popyt, a frameworki Laravel i Symfony należą do najczęściej wybieranych w nowych projektach. Umiejętności warte nauki to PHP 8.x (typy, enumy, atrybuty), Composer, testy (PHPUnit/Pest), narzędzia jak Rector i PHPStan oraz praktyka pracy z kodem legacy — bo to właśnie modernizacja starych systemów jest dziś najbardziej poszukiwaną kompetencją.

KS

Krzysztof Słonina

Full-stack developer · 16 lat doświadczenia

Przejmuję i modernizuję aplikacje PHP legacy — audyty, testy charakterystyczne, refaktoryzacja modułowa, CI/CD i monitoring. Jeśli Twój system utknął na wersji PHP po zakończeniu wsparcia, opisz go — odpowiem w ciągu 24 godzin.

O autorze

Fakty o projekcie

Ścieżka PHP
5.6 → 7.4 → 8.4 (z punktami kontrolnymi)
Czas trwania
6 miesięcy, etapami
Przestoje
zero — wdrożenia etapowe z rollbackiem
Zmodernizowane moduły
rozliczenia, raportowanie, panel admina, integracje
Siatka testów
testy charakterystyczne na krytycznych ścieżkach
Model pracy
audyt → testy → refaktoryzacja → CI/CD → monitoring

Technologie

PHP 8.4 Laravel Rector PHPStan PHPCompatibility PHPUnit GitHub Actions Docker Redis PostgreSQL New Relic

Podobny system legacy?

Bezpłatna konsultacja — zmapujemy Twój system, jego ryzyka i pierwszy bezpieczny krok.

Umów rozmowę

Powiązana usługa

Modernizacja legacy PHP

Audyt, refaktoryzacja i aktualizacja legacy PHP z testami regresji i CI/CD.

Zobacz usługę

Powiązane usługi

Powiązane artykuły

Potrzebujesz podobnego efektu?

Porozmawiajmy o Twoim projekcie. Bezpłatna konsultacja.

Umów rozmowę