# Debugowanie WordPress: od błędu krytycznego przez log do weryfikacji naprawy

> Komunikat „W witrynie wystąpił błąd krytyczny” opisuje skutek, nie przyczynę. Przejdź przez bezpieczne pozyskanie logu, odtworzenie usterki, izolację komponentu oraz kontrolę naprawy bez ujawniania błędów odwiedzającym.

Autor: WebAlpha (WebAlpha). Opublikowano: 2026-09-07. Zaktualizowano: 2026-09-07. Kanoniczny adres: https://webalpha.pl/blog/debugowanie-wordpress-blad-krytyczny

Około 22 min czytania (szacunek; bez czasu wykonania instrukcji).

> **Test laboratoryjny z 7 września 2026:** Odtworzyliśmy dwa kontrolowane błędy: wywołanie nieistniejącej funkcji i błąd składni PHP. Sprawdziliśmy HTTP 500, prywatny log, brak szczegółów w odpowiedzi, izolację, poprawny plik i końcową regresję. Cały scenariusz uzyskał 41/41 kontroli PASS; osobny przebieg wykonał polecenia z obu poradników i zaliczył 30 dodatkowych kontroli. Nie był to test produkcji klienta, płatności ani rzeczywistego dostarczenia SMTP.

Debugowanie WordPress polega na powiązaniu objawu z konkretnym zdarzeniem i sprawdzeniu przyczyny. Samo włączenie WP_DEBUG nie naprawia strony. Poniżej przechodzimy od statusu HTTP przez prywatny log PHP do odizolowania wadliwego kodu, sprawdzenia poprawki i wyłączenia diagnostyki. Wykonujemy jedną kontrolowaną procedurę w lokalnym laboratorium; nie wyłączamy wszystkich wtyczek na działającej stronie klienta.

> **Wymagany dostęp i granica instrukcji:** Potrzebujesz terminala oraz Dockera z Compose do ćwiczenia. Przy rzeczywistej stronie odpowiednikiem jest SSH/SFTP, dostęp do konfiguracji oraz logu hostingu i odseparowana kopia. Procedura dotyczy błędu PHP w pojedynczym WordPressie. Nie jest analizą włamania, awarii sieci, pełnego checkoutu WooCommerce ani instrukcją podnoszenia limitów bez diagnozy.

**Rzeczywiste środowisko testu — 7 września 2026**

| Składnik | Wersja lub zakres |
| --- | --- |
| WordPress / PHP / WP-CLI | 7.1 / 8.3.33 / 2.12.0 |
| Baza i klient SQL | MySQL 8.4.10 / MariaDB client 11.8.6 |
| Motyw | Twenty Twenty-Five 1.5 |
| Własne elementy testowe | WA Lab Fault, formularz lokalny i przechwycenie wp_mail; bez funkcji płatniczych |
| Cel diagnostyki | Odseparowany restore w Dockerze, dostęp tylko na 127.0.0.1:18882 |

<a id="sekcja-szybka-sciezka-co-zrobic-przy-awarii-swojej-strony"></a>

## Szybka ścieżka: co zrobić przy awarii swojej strony

| Dostęp, który masz | Pierwsza bezpieczna czynność | Dalsza ścieżka |
| --- | --- | --- |
| Tylko panel hostingu lub WordPressa | Zapisz URL, godzinę i ostatnią zmianę. Odczytaj pasujący log PHP w hostingu oraz dostępność ostatniej kopii. Nie aktualizuj wszystkich dodatków naraz. | Poproś o prywatną kopię i odtworzenie konkretnego błędu. Wzór zgłoszenia na końcu pozwala przekazać potrzebne dane bez haseł. |
| Panel WP nie działa, ale dostałeś Recovery Mode | Otwórz link wyłącznie samodzielnie; ustal wskazany komponent i wersję. Nie publikuj linku odzyskiwania. | Działający panel w tej sesji nie oznacza naprawy dla odwiedzających. Sprawdź zwykłe żądanie bez tej sesji i zaplanuj test na kopii. |
| Mam SFTP, ale nie mam SSH | Zabezpiecz konfigurację poza WWW i znajdź log hostingu. Na kopii można odizolować wskazaną zwykłą wtyczkę zmianą nazwy jej katalogu. | Nie zmieniaj całego wp-content. Dla MU pluginu, motywu lub niedziałającego PHP potrzebna jest inna diagnoza; nie traktuj zmiany nazwy jako naprawy funkcji. |
| Mam terminal i chcę przejść proces technicznie | Wybierz laboratorium WP z etapów 1–7 albo dodatkowy przykład funkcjonalny PHP w etapie 8. | Wymagaj wyniku tej samej czynności przed/po, a nie tylko zniknięcia HTTP 500. |

Przy awarii produkcji nie musisz najpierw budować naszego Dockera: zacznij od dowodu z własnego żądania i hostingu. Laboratorium służy nauczeniu i sprawdzeniu procedury bez danych klientów. Ścieżek konkretnego panelu hostingu nie testowaliśmy. Jeżeli błąd zatrzymuje zamówienia lub formularze, priorytetem jest ustalenie bezpiecznego sposobu przywrócenia funkcji i granicy nowych danych, nie eksperyment na działającym serwisie.

[Pobierz protokół testów i fragmenty logów](https://webalpha.pl/downloads/blog/wordpress-lab-2026-09-07-results.json)

41 kontroli, rzeczywiste wersje, dwa błędy oraz wynik końcowej weryfikacji. Wyłącznie dane syntetyczne.

<a id="sekcja-1-zapisz-objaw-zanim-zmienisz-konfiguracje"></a>

## 1. Zapisz objaw, zanim zmienisz konfigurację

Zanotuj dokładny URL, godzinę i strefę czasową, status HTTP, rodzaj żądania oraz ostatnią zmianę: aktualizację wtyczki, motywu, PHP, wdrożenie kodu lub konfiguracji. Odróżnij awarię całej strony od jednego formularza czy zadania w tle. Sprawdź, czy problem występuje również bez zalogowania i czy odpowiedź pochodzi z cache. Nie publikuj adresu z tokenem resetowania hasła ani danych POST.

**Ten sam widoczny objaw nie musi mieć tej samej przyczyny**

| Objaw | Pierwszy dowód | Gdzie szukać dalej |
| --- | --- | --- |
| Komunikat o błędzie krytycznym | Odpowiadający czasem wpis PHP Fatal/Parse error | Wtyczka, motyw lub kod wskazany w logu; cały kontekst wywołania. |
| HTTP 500 bez logu WordPress | Log serwera WWW i PHP-FPM/Apache | Błąd przed uruchomieniem WP, konfiguracja lub uprawnienia; nie każda awaria zapisze debug.log. |
| HTTP 502/504 | Log proxy oraz backendu | Niedostępny lub przeciążony proces, timeout; sam WP_DEBUG może nie dać odpowiedzi. |
| Błąd połączenia z bazą | Stan bazy i właściwa konfiguracja połączenia | Dostępność serwera, limity, poświadczenia, uprawnienia; nie wklejaj hasła do narzędzi diagnostycznych. |
| Biała strona z HTTP 200 | Treść odpowiedzi oraz log tego żądania | Cache, wyjście PHP, szablon lub JavaScript; sam status 200 nie potwierdza sprawności. |

Jeśli działa [Recovery Mode WordPress](https://wordpress.org/documentation/article/recovery-mode/), może umożliwić dostęp do panelu po części błędów krytycznych. Wstrzymanie komponentu dla sesji administratora nie naprawia automatycznie publicznej witryny. Wiadomość odzyskiwania może nie dotrzeć; zadania CRON i niektóre awarie wymagają innej drogi. Linku odzyskiwania nie przekazuj publicznie.

<a id="sekcja-2-przygotuj-kopie-na-ktorej-mozna-odtworzyc-problem"></a>

## 2. Przygotuj kopię, na której można odtworzyć problem

Przed zmianą zrób kopię plików i bazy oraz ustal sposób powrotu. Pełną procedurę z odseparowanym celem opisuje [backup WordPress i test przywracania](https://webalpha.pl/blog/kopia-zapasowa-wordpress-przywracanie). Sama kopia pliku wp-config.php zabezpiecza tylko ten plik, a nie całą stronę. Jeżeli nie potrafisz odizolować danych i wysyłek, zatrzymaj się przed uruchomieniem sklonowanej aplikacji.

[Pobierz laboratorium do diagnozy WordPress](https://webalpha.pl/downloads/blog/wordpress-lab-2026-09-07.zip)

Lokalna instalacja, syntetyczne dane, kontrolowana wtyczka i protokół wykonania bloków w evidence/results-manual.json. Nie instaluj wtyczki wywołującej błąd na produkcji.

Jeżeli wykonałeś ręczną ścieżkę poprzedniego poradnika, masz już działający cel restore i możesz przejść do kontroli bazowej poniżej. Jeżeli zaczynasz od zera, rozpakuj paczkę do nowego katalogu i w katalogu z compose.yaml uruchom polecenia przygotowania. Skrypt wymaga Node.js 20 lub nowszego, sam tworzy dane, kopię i cel, a także wykonuje automatyczny test diagnozy. Po jego zakończeniu możesz powtórzyć ręcznie wybrany scenariusz z tego artykułu. Skrypt odmawia nadpisania zainstalowanego źródła — nie uruchamiaj go ponownie po ścieżce ręcznej.

Tylko nowy, pusty projekt laboratorium — przygotowanie automatyczne

```bash
docker compose up -d --build
docker compose ps
docker compose exec -T --user www-data source test -f /var/www/html/wp-config.php
docker compose exec -T --user www-data restore test -f /var/www/html/wp-config.php
docker compose exec -T --user www-data source wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker compose exec -T --user www-data restore wp db query 'SELECT DATABASE(), @@hostname, @@server_uuid, VERSION();'
docker compose exec -T --user www-data source wp db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-names
docker compose exec -T --user www-data restore wp db query 'SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA=DATABASE();' --skip-column-names
node run.mjs
```

Przed uruchomieniem node run.mjs bazy muszą być healthy, a kontrola konfiguracji i wszystkie zapytania SQL kończyć się powodzeniem. Mają wskazywać dwa różne serwery i UUID, bazę wordpress_lab, a COUNT tabel ma wynosić 0 dla obu. Brak połączenia nie jest dowodem pustej bazy. Jeśli inicjalizacja jeszcze trwa, sprawdź docker compose logs i ponów kontrolę, nie następny krok. Po skrypcie wymagamy success=true w results.json. Przy błędzie nie resetuj hurtowo wolumenów. Ręczne polecenia diagnostyczne wykonujemy tylko na restore pod http://127.0.0.1:18882. Katalog WWW to /var/www/html, prywatny to /var/www/private; port jest dostępny wyłącznie na loopback.

Zapisz wersje i bazowy wynik odpowiedzi przed reprodukcją

```bash
docker compose exec -T --user www-data restore wp core version
docker compose exec -T restore php --version
docker compose exec -T --user www-data restore wp cli version
docker compose exec -T --user www-data restore wp plugin list --fields=name,status,version
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18882/
```

Lokalny obraz laboratorium używa połączenia z bazą bez TLS tylko wewnątrz niepublikowanej sieci jednej maszyny i wyłącznie dla syntetycznych danych. Nie jest to porada wyłączania weryfikacji certyfikatów w produkcji. Zewnętrzne połączenie hostingu wymaga prawidłowej konfiguracji TLS, CA i nazwy hosta; nie jest objęte tym ćwiczeniem.

<a id="sekcja-3-wlacz-wp-debug-z-logiem-poza-publicznym-katalogiem"></a>

## 3. Włącz WP_DEBUG z logiem poza publicznym katalogiem

Ustal, który wp-config.php jest faktycznie ładowany. W laboratorium jest w /var/www/html; na hostingu może znajdować się wyżej lub pobierać konfigurację z innych plików. Zachowaj oryginał w prywatnym katalogu. Jeśli wp-config.before-debug.php już istnieje, nie nadpisuj wcześniejszej kopii — sprawdź stan poprzedniej sesji. Sprawdź definicje WP_DEBUG, WP_DEBUG_LOG i WP_DEBUG_DISPLAY. Nie dopisuj drugiego zestawu na końcu pliku i nie kopiuj całej konfiguracji do zgłoszenia.

Kopia konfiguracji i aktualizacja konkretnych stałych w laboratorium

```bash
docker compose exec -T --user www-data restore sh -eu -c 'test ! -e /var/www/private/wp-config.before-debug.php; umask 077; cp /var/www/html/wp-config.php /var/www/private/wp-config.before-debug.php'
docker compose exec -T --user www-data restore wp config set WP_DEBUG true --raw
docker compose exec -T --user www-data restore wp config set WP_DEBUG_LOG /var/www/private/debug.log
docker compose exec -T --user www-data restore wp config set WP_DEBUG_DISPLAY false --raw
docker compose exec -T restore php -l /var/www/html/wp-config.php
```

Parametr --raw jest istotny: false ma być wartością logiczną, nie napisem 'false', który PHP traktuje jako prawdziwy. Obejrzyj wynik zmian w konfiguracji; poniższe definicje mają znajdować się przed załadowaniem wp-settings.php. W przypadku warunkowej konfiguracji lub zmiennych środowiskowych sprawdź efektywną wartość, nie tylko tekst pojedynczej linii.

Oczekiwane wartości; nie dopisuj ich drugi raz do pliku

```php
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', '/var/www/private/debug.log' );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
```

Według [dokumentacji debugowania WordPress](https://developer.wordpress.org/advanced-administration/debug/debug-wordpress/) WP_DEBUG_LOG działa przy aktywnym WP_DEBUG i może wskazywać własny plik. WP_DEBUG_DISPLAY niezależnie ogranicza wyświetlanie błędów. Dokumentacja [wp config set](https://developer.wordpress.org/cli/commands/config/set/) opisuje aktualizację stałych bez ładowania całego WordPressa. Te narzędzia przeznaczone są do diagnostyki na local/staging, nie stałego działania w produkcji.

> **Ukrycie błędu na stronie nie zabezpiecza logu:** WP_DEBUG_DISPLAY=false nie blokuje HTTP do wp-content/debug.log. W naszym środowisku plik leży poza webroot i nie ma do niego aliasu serwera. Na hostingu sprawdź rzeczywistą konfigurację. Katalog musi być zapisywalny przez użytkownika PHP, ale nie przez wszystkich; nie stosuj chmod 777. Jeśli log nie powstaje, sprawdź ścieżkę, właściciela, uprawnienia i log PHP hostingu zamiast przenosić go do publicznego katalogu.

<a id="sekcja-4-odtworz-jeden-blad-i-polacz-zadanie-z-logiem"></a>

## 4. Odtwórz jeden błąd i połącz żądanie z logiem

Najpierw wgraj i aktywuj poprawną wersję lokalnego fixture wa-lab-fault, a dopiero potem zastąp ją wariantem wywołującym nieistniejącą funkcję. Wtyczka jest dołączona do paczki jako jawny plik tekstowy. Nie ma zadania biznesowego — celowo odtwarza określoną awarię PHP. Kod błędu funkcji działa tylko w środowisku local i pomija CLI. Nawet z tym ograniczeniem nie kopiuj go na produkcję.

Kontrolowana awaria wyłącznie w restore — dane ćwiczeniowe

```bash
docker compose exec -T --user www-data restore mkdir -p wp-content/plugins/wa-lab-fault
docker compose cp fixtures/fault-fixed.php.txt restore:/var/www/html/wp-content/plugins/wa-lab-fault/wa-lab-fault.php
docker compose exec -T --user www-data restore wp plugin activate wa-lab-fault
docker compose cp fixtures/fault-function.php.txt restore:/var/www/html/wp-content/plugins/wa-lab-fault/wa-lab-fault.php
docker compose restart restore
```

Restart dotyczy tylko lokalnego kontenera restore i czyści stan OPcache, aby kolejny test uruchamiał właśnie wgrany plik. Nie jest poleceniem restartu hostingu WebAlpha ani zaleceniem restartowania dowolnej produkcji. Poczekaj, aż serwer w kontenerze ponownie zacznie odpowiadać. Zanotuj czas UTC i wywołaj jedno żądanie testowe; na prawdziwej kopii zamiast fixture odtwórz rzeczywistą czynność wywołującą awarię.

Kontrola odpowiedzi i prywatny odczyt ostatnich zdarzeń

```bash
date -u '+%Y-%m-%dT%H:%M:%SZ'
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' 'http://127.0.0.1:18882/?wa_fault=function'
docker compose exec -T --user www-data restore tail -n 40 /var/www/private/debug.log
```

Dla tego scenariusza oczekujemy HTTP 500 oraz zdarzenia Call to undefined function wa_lab_missing_function() wskazującego plik wp-content/plugins/wa-lab-fault/wa-lab-fault.php. To oczekiwanie wynikające z celowo wadliwego kodu, nie diagnoza każdej realnej strony. W treści odpowiedzi nie powinny pojawić się stos wywołań, nazwa funkcji ani prywatna ścieżka logu. Log odczytuj w terminalu i anonimizuj przed przekazaniem komukolwiek.

Czytaj typ błędu, komunikat, plik, linię oraz stos wywołań jako całość. Linia z wp-includes nie zawsze oznacza błąd samego WordPressa: mogła zostać wywołana przez dodatek z nieprawidłowymi danymi. Ostrzeżenie Deprecated sprzed tygodnia nie jest automatycznie przyczyną dzisiejszego HTTP 500. Priorytetem jest zdarzenie zgodne czasem i czynnością, którą odtworzyłeś.

**Co sprawdzać zależnie od wpisu PHP**

| Wpis | Hipoteza do sprawdzenia | Test rozróżniający |
| --- | --- | --- |
| Parse error / syntax error | Nieprawidłowa składnia lub składnia niewspierana przez używane PHP | php -l wskazanego pliku w tej samej wersji PHP; porównanie z poprawną paczką kodu. |
| Call to undefined function / Class not found | Brak zależności, niepełne wdrożenie albo zła kolejność ładowania | Sprawdzenie definicji, wersji i paczki komponentu; kontrolowane uruchomienie bez wskazanej wtyczki. |
| Allowed memory size exhausted | Za duży przebieg, pętla, wadliwe dane lub zbyt niski limit | Powtarzalna czynność i zużycie pamięci; nie podnoś limitu bez ustalenia źródła obciążenia. |
| Permission denied / failed to open stream | Brak pliku lub nieprawidłowy właściciel albo prawa | Kontrola istniejącej ścieżki i użytkownika procesu; bez nadawania globalnego zapisu. |
| Brak pasującego zdarzenia | Żądanie nie dociera do PHP albo log wskazuje inną lokalizację | Status i log proxy/serwera, konfiguracja PHP, prywatny katalog, czas i cache. |

Rzeczywisty fragment prywatnego logu z kontrolowanego testu funkcji

```text
[07-Sep-2026 12:45:53 UTC] PHP Fatal error: Uncaught Error: Call to undefined function wa_lab_missing_function() in /var/www/html/wp-content/plugins/wa-lab-fault/wa-lab-fault.php:7
```

<a id="sekcja-5-izoluj-wskazany-komponent-nie-wszystkie-dodatki-naraz"></a>

## 5. Izoluj wskazany komponent, nie wszystkie dodatki naraz

Dokładne polecenia dla błędu odtworzonego w laboratorium

```bash
docker compose exec -T --user www-data restore wp --skip-plugins=wa-lab-fault plugin deactivate wa-lab-fault
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18882/
```

Jeżeli log wskazuje zwykłą wtyczkę, na kopii pomiń jej ładowanie w WP-CLI i wyłącz tylko ją. W poleceniu użyj rzeczywistego slugu katalogu z wp-content/plugins; nazwa marketingowa z panelu nie musi być slugiem. Nie używaj --uninstall: diagnoza nie wymaga usuwania konfiguracji i danych dodatku. Zachowaj kopię wadliwej wersji do porównania.

Wzorzec dla rzeczywistej kopii; zastąp slug po identyfikacji w logu

```bash
wp --path=/rzeczywisty/katalog/wordpress --skip-plugins --skip-themes plugin deactivate SLUG_Z_LOGU
wp --path=/rzeczywisty/katalog/wordpress --skip-plugins --skip-themes plugin status SLUG_Z_LOGU
```

Dokumentacja [wp plugin deactivate](https://developer.wordpress.org/cli/commands/plugin/deactivate/) opisuje wyłączenie wskazanego komponentu. --skip-plugins pomija zwykłe wtyczki podczas uruchamiania CLI, ale nadal ładuje mu-plugins. Nie rozwiąże więc każdej awarii wp-config.php, must-use pluginu, drop-inu cache lub motywu. Jeśli CLI nadal się zatrzymuje, sprawdź jego błąd i log serwera; nie poszerzaj zakresu wyłączeń bez dowodu.

Brak SSH nie zawsze blokuje diagnozę: na kopii można przez SFTP zmienić nazwę katalogu wskazanej zwykłej wtyczki, zachowując oryginalny kod. Zanotuj zmianę i później uporządkuj status w panelu. Nie zmieniaj hurtowo nazwy całego wp-content. Przy awarii motywu potrzebny jest zainstalowany zgodny motyw zastępczy i osobny test wyglądu oraz funkcji; to nie jest neutralna zmiana produkcyjna.

> **HTTP 200 po dezaktywacji to izolacja, nie pełna naprawa:** Wyłączony formularz, moduł płatności lub integracja może przestać wywoływać błąd dlatego, że przestał działać w ogóle. To potwierdza związek komponentu ze ścieżką awarii, ale nie przywraca wymaganej funkcji. Ustal, dlaczego kod zawiódł, przygotuj poprawkę lub zgodną wersję i przetestuj również działanie dodatku po jego ponownym włączeniu.

<a id="sekcja-6-napraw-przyczyne-i-ponow-dokladnie-ten-sam-test"></a>

## 6. Napraw przyczynę i ponów dokładnie ten sam test

Przy błędzie składni porównaj plik z właściwym wydaniem i sprawdź php -l w wersji PHP używanej przez serwis. Przy brakującej funkcji ustal, czy brakuje zależności, czy aktualizacja była niepełna, czy własny kod wywołuje niewłaściwe API. Nie dopisuj pustej funkcji ani warunku function_exists tylko po to, żeby ukryć fatal error — możesz w ten sposób pominąć potrzebne działanie. Poprawka ma przywrócić konkretną funkcję, a nie jedynie wygasić komunikat.

W laboratorium ścieżka naprawy polega na zastąpieniu celowo wadliwej wersji fixture wersją poprawną i wykonaniu tego samego żądania. Na prawdziwej stronie wybierz ustaloną zgodną paczkę autora albo poprawkę własnego kodu, przetestowaną na kopii. Jeżeli zmiana wymaga cofnięcia migracji bazy, potrzebujesz zgodnego zestawu kod+baza i rozliczenia danych zapisanych od czasu kopii; sama podmiana katalogu wtyczki może nie wystarczyć.

Przywrócenie poprawnego fixture, kontrola składni i ten sam URL

```bash
docker compose cp fixtures/fault-fixed.php.txt restore:/var/www/html/wp-content/plugins/wa-lab-fault/wa-lab-fault.php
docker compose exec -T --user www-data restore php -l wp-content/plugins/wa-lab-fault/wa-lab-fault.php
docker compose restart restore
docker compose exec -T --user www-data restore wp plugin activate wa-lab-fault
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' 'http://127.0.0.1:18882/?wa_fault=function'
```

Po ponownym uruchomieniu kontenera wymagamy HTTP 200, poprawnej treści i braku nowego odpowiadającego błędu w logu. Fixture po prostu nie wywołuje już celowo nieistniejącej funkcji; nie udajemy, że ten test przywrócił funkcję rzeczywistego modułu sprzedażowego. Dla produkcyjnej wtyczki potrzebny jest osobny test jej wymaganego zachowania.

<a id="sekcja-drugi-scenariusz-blad-skladni-php"></a>

### Drugi scenariusz: błąd składni PHP

Wariant syntax to osobny test. Plik zawiera celowo nieprawidłowe przypisanie; PHP nie może go sparsować, więc żaden warunek ochronny wewnątrz tego pliku nie zdąży zadziałać. Wykonuj go wyłącznie w tym samym izolowanym restore, po zakończeniu pierwszego scenariusza. Tu php -l powinno zakończyć się błędem — jest to oczekiwany wynik próby negatywnej, nie powód do pominięcia kontroli.

Błąd składni: reprodukcja, odczyt dowodu, izolacja

```bash
docker compose cp fixtures/fault-syntax.php.txt restore:/var/www/html/wp-content/plugins/wa-lab-fault/wa-lab-fault.php
docker compose restart restore
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' 'http://127.0.0.1:18882/?wa_fault=syntax'
docker compose exec -T --user www-data restore tail -n 40 /var/www/private/debug.log
docker compose exec -T --user www-data restore php -l wp-content/plugins/wa-lab-fault/wa-lab-fault.php
docker compose exec -T --user www-data restore wp --skip-plugins=wa-lab-fault plugin deactivate wa-lab-fault
```

W logu szukaj Parse error lub syntax error z tego żądania. Po izolacji powtórz blok przywrócenia poprawnego fixture z poprzedniej sekcji, zmieniając kontrolny URL na /?wa_fault=syntax. Dopiero powrót prawidłowej odpowiedzi po aktywacji poprawionej wtyczki zamyka ten scenariusz. Nie zostawiaj wadliwego pliku na koniec ćwiczenia.

Rzeczywisty fragment drugiego zdarzenia z testu składni

```text
[07-Sep-2026 12:45:58 UTC] PHP Parse error: syntax error, unexpected token ";" in /var/www/html/wp-content/plugins/wa-lab-fault/wa-lab-fault.php on line 5
```

W wykonanym teście oba błędy dały HTTP 500 i prywatny wpis logu, ale szczegóły błędu nie trafiły do treści odpowiedzi. Po izolacji uzyskaliśmy HTTP 200; po wgraniu poprawnego fixture i ponownej aktywacji również HTTP 200. Kontrola php -l dla uszkodzonej składni zakończyła się kodem 255 i wskazała błąd. To obserwacje dla powyższych plików, nie uniwersalne rozpoznanie wszystkich błędów krytycznych.

Dodatkowo można sprawdzić integralność core przez [wp core verify-checksums](https://developer.wordpress.org/cli/commands/core/verify-checksums/), podając właściwe --version i --locale. Wynik dotyczy plików rdzenia, nie bezpieczeństwa całej witryny ani poprawności wtyczek. Nie wyłączaj walidacji TLS, gdy narzędzie nie może pobrać sum; najpierw diagnozuj połączenie. W odseparowanym laboratorium takie pobieranie może być świadomie zablokowane.

- Ponów ten sam URL i tę samą czynność, również bez aktywnej sesji Recovery Mode.
- Sprawdź status, oczekiwaną treść odpowiedzi oraz wpisy logu utworzone od momentu poprawki. Sam brak nowego logu nie wystarcza, jeśli żądanie nie dotarło do PHP.
- Zweryfikuj funkcję naprawianej wtyczki; dezaktywacja nie jest testem jej działania.
- Na rzeczywistej kopii sprawdź panel, kluczowe podstrony, formularz do testowego odbiornika i wymagane integracje z danymi testowymi. Nie wysyłaj próbnych wiadomości klientom.
- Zapisz wersję wadliwą i poprawioną, zakres zmiany, wyniki oraz plan powrotu. Dopiero wtedy ustal osobne okno wdrożenia produkcyjnego.

<a id="sekcja-7-wylacz-debugowanie-i-sprawdz-prywatnosc-logu"></a>

## 7. Wyłącz debugowanie i sprawdź prywatność logu

Po testach porównaj konfigurację ze stanem sprzed diagnozy. Jeżeli nie zmieniałeś innych ustawień, można odtworzyć zachowaną kopię wp-config.php. Jeżeli w międzyczasie zmieniły się poświadczenia lub inne ustawienia, nie nadpisuj ich starym plikiem — przywróć tylko odpowiednie stałe. W naszym lokalnym scenariuszu stan końcowy ma wyłączone debugowanie i wyświetlanie błędów.

Jawne zamknięcie diagnostyki w lokalnym laboratorium

```bash
docker compose exec -T --user www-data restore wp config set WP_DEBUG false --raw
docker compose exec -T --user www-data restore wp config set WP_DEBUG_LOG false --raw
docker compose exec -T --user www-data restore wp config set WP_DEBUG_DISPLAY false --raw
docker compose exec -T restore php -l /var/www/html/wp-config.php
docker compose exec -T --user www-data restore wp eval 'echo wp_json_encode(array("WP_DEBUG" => WP_DEBUG, "WP_DEBUG_LOG" => WP_DEBUG_LOG, "WP_DEBUG_DISPLAY" => WP_DEBUG_DISPLAY));'
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18882/
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18882/wp-content/debug.log
curl --silent --show-error --output /dev/null --write-out '%{http_code}\n' http://127.0.0.1:18882/private/debug.log
```

Dla obu prób pliku logu oczekujemy braku publicznej treści; prawidłowym wynikiem w naszym układzie jest 404. Na innym serwerze może to być np. 403, ale trzeba sprawdzić również treść odpowiedzi i konfigurację aliasów — jedna próba URL nie dowodzi prywatności wszystkich ścieżek. Wyłączenie WP_DEBUG_LOG nie usuwa starego logu. Zachowaj potrzebny, zanonimizowany dowód w prywatnym miejscu, a pozostałe dane usuń zgodnie z ustaloną retencją. Nie kasuj logów incydentu bezpieczeństwa bez zabezpieczenia dowodów.

Potwierdzone efektywne wartości PHP po zamknięciu testu

```json
{"WP_DEBUG":false,"WP_DEBUG_LOG":false,"WP_DEBUG_DISPLAY":false}
```

Końcowy test potwierdził powyższe booleany, HTTP 404 dla /wp-content/debug.log i /private/debug.log oraz działające logowanie i lokalny formularz. Odczytujemy efektywne stałe w PHP, a nie interpretujemy pustego wyniku wp config get jako błąd: dla wartości false ten interfejs CLI może zwrócić pusty tekst.

Na produkcji ustawienie display_errors należy sprawdzić także w konfiguracji PHP serwera. Błąd składni samego wp-config.php może wystąpić zanim WordPress zastosuje swoje stałe. Log PHP hostingu może i powinien działać niezależnie od wyłączonego WP_DEBUG; zakończenie tymczasowej diagnostyki nie oznacza wyłączenia całego monitoringu błędów.

<a id="sekcja-8-napraw-funkcje-nie-tylko-status-kalkulator-czasu-czytania"></a>

## 8. Napraw funkcję, nie tylko status: kalkulator czasu czytania

Powyższa wtyczka wa-lab-fault uczy izolacji deterministycznych błędów. Drugi, odrębny przykład ma konkretną funkcję: shortcode wa_reading_time wyświetla oszacowanie czasu czytania na podstawie liczby słów i przyjętej przez redaktora prędkości. Dla 901 słów oraz 200 słów/min wynik ma wynosić 5 min. Nie jest to automatyczny pomiar zachowania czytelników ani wyliczanie słów dowolnego języka z HTML.

[Pobierz funkcjonalną wtyczkę, testy i protokół rozszerzenia](https://webalpha.pl/downloads/blog/wordpress-praktyka-2026-09-07.zip)

Dwa pliki wtyczki, testy PHP i scenariusz HTTP. Osobne dowody: 37 kontroli natywnych oraz 23 kontrole rzeczywistego WP i 4 kontrole przywrócenia stanu, obejmujące też kopię szyfrowaną. Bez danych klienta.

> **Sprawdzone w PHP i osobno w rzeczywistym WordPressie:** Dnia 7.09.2026 PHP 8.5.5 zaliczył 20 kontroli funkcji i minimalnych adapterów oraz 6 kontroli HTTP/naprawy/regresji. Następnie o 13:35 UTC osobny przebieg uruchomił tę wtyczkę w WordPressie 7.1/PHP 8.3.33: prawdziwy shortcode zwrócił 5 min, błąd wywołał 500 i prywatny log, a poprawka przywróciła temu samemu żądaniu 200 oraz 5 min. Rzeczywisty core potwierdził też granice, błędną prędkość i escapowanie. Cztery kontrole końcowe potwierdziły usunięcie tylko własnej strony, wycofanie dodatku, przywrócenie konfiguracji i poprzednich danych. To nowy dowód, oddzielny od wcześniejszego WP 41/41; nie test Twojego hostingu i motywu.

<a id="sekcja-a-zdefiniuj-kontrakt-i-uruchom-test-przed-zmiana"></a>

### A. Zdefiniuj kontrakt i uruchom test przed zmianą

Shortcode dla prywatnej strony testowej — pełne pliki są w dodatku

```text
[wa_reading_time words="901" wpm="200" label="Czas czytania"]
```

Dodatek zawiera reading-time.php z czystą funkcją oraz wa-reading-time.php z rejestracją shortcode i bezpiecznym wynikiem HTML. Nie kopiuj do WordPressa pliku reading-time.test.php ani adaptera HTTP; są tylko narzędziami testowymi. Najpierw w katalogu rozpakowanego dodatku uruchom test PHP. Wymaga PHP 8 lub nowszego; nasz rzeczywisty wynik dotyczy 8.5.5.

Natywny test bez WordPressa, bazy i instalowania wtyczki na hostingu

```bash
php -l reading-time.php
php -l wa-reading-time.php
php reading-time.test.php
```

| Dane wejściowe | Wymagany wynik | Dlaczego ten test ma znaczenie |
| --- | --- | --- |
| words=901, wpm=200 | 5 min | Zaokrąglenie w górę — samo HTTP 200 mogłoby ukrywać błędne 4 min. |
| words=200 oraz words=201, wpm=200 | Odpowiednio 1 i 2 min | Granica pełnej minuty. |
| words=0 | 0 min | Jawny przypadek pustej treści. |
| wpm=0, ujemne lub ułamkowe words | Komunikat błędnych parametrów, bez dzielenia przez zero | Walidacja przed obliczeniem, bez losowego podnoszenia limitów. |
| Etykieta zawierająca <script> | Tekst escapowany, nie aktywny znacznik | Odbiór obejmuje wyjście, a nie wyłącznie wynik liczbowy; w natywnym teście jest to kontrola adaptera. |

<a id="sekcja-b-powiaz-log-z-blednym-wywolaniem-i-zastosuj-maly-diff"></a>

### B. Powiąż log z błędnym wywołaniem i zastosuj mały diff

W kontrolowanej próbie wersja wadliwa wywoływała minutes_legacy(), chociaż plik reading-time.php definiował minutes(). To nie brak losowej wtyczki ani zbyt niski limit pamięci: nazwa wywołania nie odpowiadała dostępnej funkcji we wspólnej przestrzeni nazw. Log wskazał dokładnie ten błąd. Naprawa zmienia jedno wywołanie, zachowuje walidację parametrów i naprawdę przywraca wyliczenie.

Zmiana odtworzona natywnie i w rzeczywistym WordPressie; nie dodajemy pustej funkcji

```diff
- $minutes = minutes_legacy($attributes['words'], $attributes['wpm']);
+ $minutes = minutes($attributes['words'], $attributes['wpm']);
```

Rzeczywisty prywatny log próby WordPress, 7.09.2026 13:35:22 UTC — istotna linia

```text
[07-Sep-2026 13:35:22 UTC] PHP Fatal error: Uncaught Error: Call to undefined function WebAlpha\ReadingTime\minutes_legacy() in /var/www/html/wp-content/plugins/wa-reading-time/wa-reading-time.php:23
```

Możesz odtworzyć cały test poleceniem niżej. Runner uruchomi tylko własny serwer PHP na losowym porcie 127.0.0.1, zachowa prywatny log poza jego webroot i po próbie zatrzyma własny proces. Najpierw wymaga 200 i „5 min”, potem odtwarza błędne wywołanie i 500, podmienia je na poprawne i ponawia ten sam URL. Test kończy się dopiero przy identycznym wyniku funkcji i zaliczonej regresji, a nie po samej dezaktywacji kodu. Wykonuje też opisane w poradniku backupu testy GnuPG; wymaga Node.js 20+, GnuPG, PHP i tar.

Nowa nazwa wyniku — istniejący protokół nie jest nadpisywany

```bash
node test-native.mjs ./native-results-new.json
```

Osobny pełny test WP z dodatku wymaga wcześniej ukończonego syntetycznego laboratorium z poradnika backupu. Nie uruchamiaj ponownie seedowania na zachowanych danych. Wskaż katalog bazowej paczki z compose.yaml, a polecenie niżej wykonaj z katalogu dodatku. Runner sprawdza izolację, eksportuje zestaw do nowej bazy/prywatnego katalogu, a funkcję wtyczki testuje na istniejącym restore:18882. Potrzebuje kilkuset MB na nową próbę. Chwilowo restartuje wyłącznie restore i po teście przywraca konfigurację oraz poprzednie dane; nie uruchamiaj w tym czasie innych zmian. JSON musi zawierać success:true, 23 zaliczone kontrole i 4 zaliczone kontrole cleanup.

Osobny test rzeczywistego core WP — po przygotowaniu laboratorium, bez resetu baz

```bash
WA_WORDPRESS_LAB='/pelna/sciezka/wordpress-lab-2026-09-07' \
  node test-wordpress.mjs ./wordpress-results-new.json
```

<a id="sekcja-c-oddzielnie-odbierz-integracje-na-swoim-wordpressie"></a>

### C. Oddzielnie odbierz integrację na swoim WordPressie

1. Na odseparowanej kopii, po backupie, umieść wyłącznie reading-time.php i wa-reading-time.php w nowym katalogu wp-content/plugins/wa-reading-time. Jeżeli taki katalog już istnieje, nie nadpisuj go. Zapisz pierwotny stan i aktywuj dodatek w panelu kopii.
2. Utwórz prywatną stronę testową z blokiem Shortcode i podanym wyżej przykładem. Sprawdź wyrenderowane 5 min, a nie surowy tekst shortcode. Powtórz przypadki z tabeli. Wynik testu adaptera PHP nie zastępuje tego kroku.
3. Sprawdź działające wcześniej strony i formularz. Wycofanie nowego dodatku ma usuwać tylko nowy shortcode/wtyczkę z kopii; nie cofaj całej bazy z nowszymi danymi. Nie wprowadzaj celowo minutes_legacy na produkcji, żeby „udowodnić” 500.
4. Zapisz wersję WordPressa, PHP, motywu, wynik rzeczywistego renderowania i regresji. Nasz zaliczony test WP dotyczy opisanej konfiguracji laboratoryjnej; dopóki nie wykonasz własnego odbioru, zgodność z Twoją witryną pozostaje niepotwierdzona. Nie instaluj automatycznie dodatku na produkcji po samym zielonym wyniku laboratorium.

Parametry shortcode, wartości domyślne i zabezpieczanie wyniku opisuje [oficjalna dokumentacja Shortcodes with Parameters](https://developer.wordpress.org/plugins/shortcodes/shortcodes-with-parameters/). Nasz przykład ilustruje tę metodę, a nie zastępuje testu zgodności z dodatkami Twojej witryny.

<a id="sekcja-co-przekazac-do-dalszej-diagnozy-jesli-blad-pozostal"></a>

## Co przekazać do dalszej diagnozy, jeśli błąd pozostał

Szablon zgłoszenia bez sekretów

```text
Czas i strefa: YYYY-MM-DD HH:MM:SS UTC
Objaw i status HTTP:
Ścieżka URL bez tokenów i danych osobowych:
Ostatnia zmiana i jej wersja:
WordPress / PHP / motyw / wskazana wtyczka:
Dokładna czynność odtwarzająca problem:
Zanonimizowany fragment logu z tego żądania:
Co sprawdzono na kopii i z jakim wynikiem:
Stan kopii zapasowej i sposób przywracania:
Czy błąd blokuje formularze, płatności lub administrację:
```

Nie przesyłaj całego wp-config.php, cookies, linku Recovery Mode ani pełnego dumpa przez zwykły formularz. W [usłudze naprawy WordPress](https://webalpha.pl/naprawa-wordpress) zakres i sposób bezpiecznego udostępnienia danych ustalamy przed pracą. Po usunięciu przyczyny warto objąć stronę [opieką techniczną z testami i monitoringiem](https://webalpha.pl/opieka-techniczna/strony), żeby kolejna aktualizacja miała właściciela, dowód odbioru i plan powrotu.

## Błąd nadal występuje lub dotyczy krytycznej funkcji?

Opisz moment awarii, ostatnią zmianę, wersje i wykonane próby. Ustalimy zakres diagnozy oraz sposób bezpiecznego przekazania logów. Nie dołączaj haseł, tokenów, cookies ani danych klientów do zgłoszenia.

[Zobacz zakres naprawy WordPress](https://webalpha.pl/naprawa-wordpress)

## Najczęstsze pytania (FAQ)

### Czy WP_DEBUG naprawia błąd krytyczny WordPressa?

Nie. Umożliwia zebranie informacji diagnostycznych. Naprawa wymaga powiązania błędu z konkretnym żądaniem, znalezienia przyczyny i sprawdzenia poprawki. Samo ukrycie błędu lub wyłączenie wtyczki nie przywraca jej funkcji.

### Gdzie jest debug.log w WordPressie?

Przy WP_DEBUG_LOG=true zwykle w katalogu wp-content. Możesz wskazać własną ścieżkę pliku, np. w prywatnym katalogu poza webroot. WP_DEBUG musi być aktywne, a użytkownik PHP musi mieć prawo zapisu. Wartość WP_DEBUG_DISPLAY=false nie chroni samego pliku przed pobraniem przez HTTP.

### Dlaczego log nie powstaje mimo włączenia debugowania?

Sprawdź efektywne wartości stałych, właściwy plik konfiguracji, ścieżkę i uprawnienia. Żądanie może kończyć się w proxy lub serwerze przed uruchomieniem WordPressa. Wtedy potrzebny jest log hostingu lub PHP, a nie kolejne zmiany WP_DEBUG.

### Czy mogę wyłączyć wtyczkę, jeśli panel WordPress nie działa?

Na odseparowanej kopii możesz użyć WP-CLI z --skip-plugins i --skip-themes do wyłączenia wskazanej zwykłej wtyczki. Mu-plugins nadal są ładowane. Alternatywą przy dostępie SFTP jest kontrolowana zmiana nazwy właściwego katalogu. Najpierw zapisz stan, zabezpiecz kopię i ustal wpływ wyłączenia.

### Czy po naprawie mogę zostawić WP_DEBUG włączone?

Nie powinien to być domyślny stan działającej produkcji. Zakończ tymczasową diagnostykę, przywróć właściwą konfigurację, sprawdź brak wyświetlania błędów i prywatność pozostałego logu. Utrzymuj oddzielny monitoring błędów serwera i aplikacji.
