Aktualizacja wersji PHP w istniejącej aplikacji nie polega wyłącznie na zmianie obrazu kontenera lub konfiguracji serwera. Runtime współdziała z kodem, rozszerzeniami, bibliotekami Composer oraz procesami wykonującymi zadania zaplanowane i zadania w tle. Zmiana może wpłynąć na każdy z tych elementów, nawet jeśli podczas ręcznego testu aplikacja wydaje się działać normalnie.
Niepewność można ograniczyć, traktując aktualizację jako zmianę dotyczącą kompatybilności: zinwentaryzować uruchamiane elementy, poszukać niezgodności, zweryfikować reprezentatywne ścieżki i z góry określić, jak zdecydować, czy wdrożenie będzie kontynuowane, czy zostanie wycofane. Celem jest wyodrębnienie pracy niezbędnej dla nowego runtime’u, a nie przekształcenie aktualizacji w przepisanie produktu.
Runtime jest częścią kompatybilności aplikacji

Wersja PHP określa, jaką składnię obsługuje interpreter oraz jak zachowują się określone funkcje i typy. Określa także, które wersje rozszerzeń i zależności można zainstalować. Dlatego fakt, że kod działał w obecnym środowisku, nie dowodzi, że będzie działać w nowym: może zmienić się funkcja, interfejs, zachowanie typów lub dostępność rozszerzenia.
Warto rozróżnić trzy obszary: kod aplikacji, zależności zewnętrzne i konfigurację środowiska. Jeśli wszystkie trzy zostaną zmienione jednocześnie, trudniej będzie przypisać przyczynę awarii. Zaplanowana aktualizacja rozdziela te zmiany, o ile jest to wykonalne, i jasno wskazuje, który komponent spowodował każdą modyfikację.
Zinwentaryzuj runtime, zależności i procesy
Zanim cokolwiek zmienisz, zapisz informacje o rzeczywistym środowisku uruchomieniowym, a nie tylko o tym, które opisuje plik konfiguracyjny projektu. Sprawdź wersję PHP w kontenerach lub na serwerach obsługujących żądania, a także w tych, które uruchamiają zadania zaplanowane, konsumentów kolejek i polecenia konserwacyjne. Te procesy mogą korzystać z innych obrazów, zmiennych lub rozszerzeń.
- Runtime i rozszerzenia: określ, które rozszerzenia są włączone, jakie są ich wersje (jeśli ma to zastosowanie) oraz od jakich bibliotek systemowych zależą. Porównaj wymagania produkcji, CI i środowiska deweloperskiego.
- Zależności Composer: przejrzyj
composer.json, plik blokady oraz deklarowane przez pakiety ograniczenia dotyczące wersji PHP. Sprawdź również narzędzia deweloperskie, takie jak analizatory i narzędzia do uruchamiania testów. - Konfiguracja: zinwentaryzuj wartości
php.ini, limity pamięci i czasu, konfigurację błędów oraz ustawienia specyficzne dla serwera. Nowy runtime nie gwarantuje zachowania istotnych parametrów. - Praca poza żądaniami webowymi: uwzględnij cron, kolejki, polecenia konsoli, importy, eksporty i zadania długotrwałe. Poprawne działanie ścieżki webowej nie potwierdza automatycznie poprawności tych przepływów.
- Integracje i dane: zanotuj usługi zewnętrzne, wymieniane formaty oraz zapisy do baz danych lub magazynów danych. Ułatwi to ustalenie, które operacje wymagają szczególnej uwagi podczas wycofywania zmiany.
Inwentaryzacja może być listą przechowywaną w repozytorium lub dokumentacji operacyjnej, pod warunkiem że pozwala porównywać środowiska i wykrywać rozbieżności. Częstym objawem niekompletnej inwentaryzacji jest sytuacja, w której CI przechodzi pomyślnie, ale po wdrożeniu awarii ulega worker lub zadanie zaplanowane.
Szukaj niezgodności, korzystając z różnych sygnałów
Zacznij od narzędzi automatycznych: sprawdź ograniczenia platformy w Composerze i uruchom weryfikację zależności z docelową wersją PHP. Konflikt podczas rozwiązywania zależności wskazuje, że jakiś pakiet — w tym narzędzia deweloperskie — nie deklaruje zgodności z tą platformą. Nie należy wymuszać instalacji, aby ukryć konflikt, bez zrozumienia, które wymaganie jest w ten sposób omijane.
Uzupełnij tę analizę narzędziami do analizy statycznej oraz dostępnymi w projekcie testami stylu lub kompatybilności. Mogą one wskazać podejrzane użycia, przestarzałe API lub wzorce wymagające sprawdzenia, ale same w sobie nie dowodzą, że cała aplikacja działa. Podobnie analiza bez zgłoszonych problemów nie zastępuje rzeczywistego uruchomienia: niektóre błędy pojawiają się dopiero podczas przechodzenia rzadko używaną ścieżką lub ładowania rozszerzenia.
Uruchom testy z docelowym runtime’em i rozszerzeniami przewidzianymi dla produkcji. Jeśli zestaw testów jest ograniczony, dodaj ręczne lub automatyczne kontrole przepływów o największym znaczeniu: uwierzytelniania, operacji zapisu, płatności (jeśli występują), generowania dokumentów i kluczowych integracji. Rejestruj również błędy i ostrzeżenia; zmiana, która przekształca ostrzeżenie w wyjątek, może przerwać działanie ścieżki, zanim wykryje to zestaw testów.
Zaplanuj pracę tak, aby odizolować ryzyko
Praktyczna kolejność działań to najpierw potwierdzenie kandydującego obrazu lub konfiguracji oraz rozszerzeń, następnie rozwiązanie ograniczeń zależności, a na końcu poprawienie kodu i ustawień uniemożliwiających uruchomienie testów. Każda grupa zmian powinna nadawać się do przeglądu. Jeśli biblioteka wymaga aktualizacji, udokumentuj, jakie wymaganie ją wymusza, i przetestuj obszary aplikacji, w których jest używana.
Unikaj bezrefleksyjnej aktualizacji wszystkich zależności w ramach tego samego kroku. Szeroka aktualizacja może być konieczna, ale zwiększa liczbę możliwych przyczyn regresji. Jeśli nie da się jej rozdzielić, zapisz, które pakiety uległy zmianie, i dodaj testy ukierunkowane na funkcje od nich zależne. Upewnij się również, że plik blokady jest generowany i instalowany w spójny sposób w CI i na produkcji.
Konfiguracja powinna odzwierciedlać środowisko docelowe. Walidacja z rozszerzeniem zainstalowanym tylko w CI daje mylący sygnał; podobnie jest, gdy zadania w tle nadal działają na poprzednim runtime’ie. Zanim przypiszesz wynik kodowi, porównaj obrazy, polecenia startowe, zmienne i konfigurację środowiska testowego oraz produkcyjnego.
Zweryfikuj zmianę w reprezentatywnym środowisku i określ kryteria zakończenia
CI powinno wykonywać instalację, analizę i testy z docelowym runtime’em, a nie tylko z obecnym. Dodaj osobne zadania dla innych runtime’ów wyłącznie wtedy, gdy aplikacja ma zachować okres kompatybilności — w takim przypadku każda obsługiwana kombinacja wymaga jawnej weryfikacji. Macierz CI może pokazać, które kombinacje są testowane, ale nie obejmuje automatycznie specyfiki produkcji.
Korzystaj ze środowiska przedprodukcyjnego, które jest wystarczająco podobne do rzeczywistego, aby sprawdzić uruchamianie, krytyczne ścieżki, integracje, kolejki i zadania zaplanowane. Przed wdrożeniem i po nim sprawdzaj logi, błędy, czasy odpowiedzi i zużycie zasobów. Z góry określ, jakie zachowanie zatrzyma wdrożenie, kto podejmie tę decyzję i jak długo system będzie obserwowany. Progi powinny wynikać z potrzeb aplikacji i dostępnych sygnałów, a nie z ogólnych wartości.
Przydatne kryteria zakończenia obejmują: powtarzalną instalację, uzgodniony zestaw testów zakończony powodzeniem, zweryfikowane krytyczne przepływy, brak niewyjaśnionych nowych błędów oraz możliwość obsługi procesów w tle. Zapisz znane wyjątki i przypisz do nich osoby odpowiedzialne. Samo stwierdzenie „testy przechodzą” nie wystarczy, jeśli zestaw nie obejmuje kluczowej integracji albo zespół nie wie, którą metrykę należy monitorować.
Wdrażaj z możliwością wycofania zgodną z danymi
Jeśli pozwalają na to architektura i platforma, udostępniaj nowy runtime stopniowo: najpierw w kontrolowanym środowisku, a następnie części ruchu lub mocy obliczeniowej. Stopniowe udostępnianie to strategia wdrożenia, a nie ujawnianie informacji. Nie zawsze da się rozdzielić żądania między wersje — na przykład w przypadku procesów stanowych lub różnic w protokole wewnętrznym. W takiej sytuacji zaplanuj skoordynowane przejście i jawnie sprawdź konsumentów oraz producentów komunikatów.
Przed wdrożeniem sprawdź, czy w razie awarii będzie można ponownie uruchomić poprzedni kod. Wycofanie zmiany nie polega wyłącznie na przywróceniu obrazu: migracja bazy danych, nowy format komunikatu lub niekompatybilny zapis mogą uniemożliwić poprzedniemu runtime’owi odczyt danych utworzonych przez nowy. Preferuj etapowe, kompatybilne zmiany schematu: najpierw rozszerz schemat, następnie wdroż kod obsługujący obie postacie, a starą usuń, gdy nie będą już z niej korzystać żadne procesy. Dla każdego nieodwracalnego kroku określ osobną procedurę odzyskiwania i kryterium zatrzymania.
Podczas wdrożenia monitoruj błędy aplikacji i runtime’u, awarie workerów, opóźnienia kolejek, zadania zaplanowane oraz istotne sygnały biznesowe. Jeśli zostanie spełnione kryterium wycofania, zatrzymaj rozszerzanie zmiany i postępuj zgodnie ze sprawdzoną procedurą. Zachowaj logi potrzebne do ustalenia przyczyny; wycofanie zmiany bez diagnozy może doprowadzić do ponownego wystąpienia tej samej awarii przy kolejnej próbie.
Lista kontrolna ułatwiająca ocenę gotowości

- Czy zidentyfikowano runtime i rozszerzenia we wszystkich środowiskach i procesach?
- Czy sprawdzono ograniczenia Composer oraz narzędzia deweloperskie?
- Czy analizy i testy są uruchamiane z docelową konfiguracją?
- Czy przetestowano krytyczne ścieżki, integracje, kolejki i zadania zaplanowane?
- Czy znane są różnice między CI, środowiskiem przedprodukcyjnym i produkcją?
- Czy istnieją sygnały operacyjne, osoby odpowiedzialne i jasne kryteria kontynuacji lub zatrzymania?
- Czy poprzedni kod może obsługiwać dane i komunikaty tworzone przez nowy?
- Czy przećwiczono wycofanie zmiany i wiadomo, których modyfikacji nie da się automatycznie cofnąć?
Decyzja o aktualizacji wersji PHP w istniejącej aplikacji jest bardziej wiarygodna, gdy zespół potrafi odpowiedzieć na te pytania, opierając się na dowodach. Jeśli brakuje testów lub inwentaryzacji, kolejnym krokiem nie musi być przepisanie aplikacji: można najpierw uzupełnić te braki i ograniczyć zakres zmiany. Dzięki temu potencjalne awarie zostaną wykryte, zanim wpłyną na użytkowników, a każda decyzja dotycząca wdrożenia będzie miała weryfikowalne kryterium.



