Zmiana domeny w WordPress — jak zaktualizować bazę danych
Po zmianie adresu obrazki i linki wciąż prowadzą do starej domeny. Komenda WP-CLI, gotowe zapytania SQL i dwie pułapki, które po cichu psują bazę.

Po przeniesieniu WordPressa na nową domenę adresy w bazie zostają stare. Najszybciej naprawia to jedna komenda WP-CLI: wp search-replace 'https://stara-domena.pl' 'https://nowa-domena.pl'. Jeśli nie masz dostępu do konsoli, niżej znajdziesz wersję przez phpMyAdmin.
Zanim jednak skopiujesz pierwsze lepsze zapytanie z internetu: dwa z popularnie powielanych poleceń potrafią rozbić ustawienia motywu i wtyczek tak, że objawy wyjdą dopiero po kilku dniach. Opisuję je w dalszej części.
Dlaczego zmiana adresu w kokpicie nie wystarcza
WordPress trzyma adres strony w kilku miejscach naraz. W tabeli wp_options siedzą pola home i siteurl. W wp_posts każdy wstawiony obrazek, link wewnętrzny i osadzony materiał zapisany jest jako adres bezwzględny, czyli https://stara-domena.pl/wp-content/uploads/2024/03/zdjecie.jpg zamiast samego /zdjecie.jpg. Własne adresy zapisują też motywy i wtyczki, w wp_postmeta i we własnych tabelach.
Zmiana home i siteurl przestawia tylko to, pod jakim adresem WordPress widzi sam siebie. Treść wpisów zostaje nietknięta i dalej wskazuje starą domenę.
Ta sama zasada dotyczy sklepów. W WooCommerce dochodzą jeszcze adresy w danych produktów i konfiguracji bramek płatności, więc migracja sklepu wymaga sprawdzenia większej liczby miejsc niż zwykła witryna.
Zacznij od kopii bazy
Każda operacja z tego tekstu zmienia dane nieodwracalnie:
mysqldump -u uzytkownik -p nazwa_bazy > kopia-przed-migracja.sql
ls -lh kopia-przed-migracja.sql
Drugie polecenie nie jest ozdobnikiem. Kopia o zerowym rozmiarze wygląda w panelu hostingu identycznie jak poprawna i przekonujesz się o tym w najgorszym momencie.
Sposób pierwszy: WP-CLI
Mając dostęp do konsoli, używaj wyłącznie tej metody. WP-CLI rozumie dane serializowane i przelicza je przy zamianie, czego zwykłe zapytanie SQL nie potrafi.
Najpierw przebieg próbny, który niczego nie zmienia, a pokazuje liczbę trafień:
wp search-replace 'https://stara-domena.pl' 'https://nowa-domena.pl' --dry-run
Gdy liczby się zgadzają, to samo bez --dry-run:
wp search-replace 'https://stara-domena.pl' 'https://nowa-domena.pl'
Domyślnie WP-CLI przechodzi po tabelach z prefiksem instalacji. Jeśli wtyczki założyły tabele poza tym prefiksem, dołóż --all-tables.
Adres podawaj bez ukośnika na końcu i dokładnie w takiej postaci, w jakiej występuje w bazie. Zamianę powtórz osobno dla każdego wariantu: https://, http:// oraz wersji z www, jeśli była używana. Próba załatwienia wszystkiego jednym wyrażeniem kończy się adresami w rodzaju https://www.https://nowa-domena.pl.
Sposób drugi: zapytania SQL
Kiedy zostaje tylko phpMyAdmin albo Adminer, wykonaj poniższe zapytania. Dotykają wyłącznie pól, w których dane nie są serializowane, więc są bezpieczne.
UPDATE wp_options
SET option_value = REPLACE(option_value, 'https://stara-domena.pl', 'https://nowa-domena.pl')
WHERE option_name IN ('home', 'siteurl');
UPDATE wp_posts
SET post_content = REPLACE(post_content, 'https://stara-domena.pl', 'https://nowa-domena.pl');
UPDATE wp_posts
SET post_excerpt = REPLACE(post_excerpt, 'https://stara-domena.pl', 'https://nowa-domena.pl');
UPDATE wp_comments
SET comment_content = REPLACE(comment_content, 'https://stara-domena.pl', 'https://nowa-domena.pl');
Prefiks wp_ bywa inny. Sprawdź go w wp-config.php w zmiennej $table_prefix i podmień w zapytaniach.
Po wykonaniu policz, czy coś zostało:
SELECT COUNT(*) FROM wp_posts WHERE post_content LIKE '%stara-domena.pl%';
Pułapka pierwsza: dane serializowane
W sieci krąży wersja tej instrukcji z dodatkowym zapytaniem na metadanych:
UPDATE wp_postmeta SET meta_value = REPLACE(meta_value, 'stara', 'nowa');
To właśnie ono psuje strony po migracji. PHP zapisuje tam tablice w formacie serializowanym, w którym przed każdym tekstem stoi jego długość:
a:1:{s:3:"url";s:32:"https://stara-domena.pl/logo.png";}
Liczba 32 to liczba znaków adresu. Po zamianie na krótszą lub dłuższą domenę adres się zmienia, a liczba zostaje. PHP próbuje odczytać 32 znaki tam, gdzie jest ich 30, i porzuca odczyt całej tablicy.
Objawy wychodzą z opóźnieniem: znikają ustawienia motywu, przestaje działać suwak na stronie głównej, konfiguracja formularza kontaktowego wraca do stanu domyślnego, pola dodatkowe przy wpisach są puste. Baza wygląda na kompletną, bo dane fizycznie w niej są. Po prostu nie da się ich odczytać.
Pola serializowane zostaw narzędziom, które przeliczają długości od nowa: WP-CLI, wtyczce Better Search Replace albo skryptowi Search Replace DB. Nigdy zwykłemu REPLACE.
Pułapka druga: kolumna guid
Ta sama popularna instrukcja każe zaktualizować guid w tabeli wp_posts. Nie rób tego.
Mimo że guid wygląda jak adres, pełni rolę trwałego identyfikatora wpisu. Czytniki RSS rozpoznają po nim, które wpisy już pokazały. Po zmianie wartości wszystkie archiwalne wpisy zostaną uznane za nowe i subskrybenci dostaną powiadomienia o kilkuset publikacjach naraz. Dokumentacja WordPressa wprost odradza modyfikowanie tej kolumny.
Stara domena w guid niczego nie psuje, bo ta wartość nie służy do budowania odnośników na stronie.
Cztery rzeczy do sprawdzenia po zamianie
Wyloguj się i zaloguj ponownie. Ciasteczko sesji jest przypisane do starej domeny, więc kokpit potrafi odsyłać do ekranu logowania w kółko.
Zapisz ustawienia odnośników. Kokpit, Ustawienia, Bezpośrednie odnośniki, przycisk Zapisz bez zmieniania czegokolwiek. To przebudowuje reguły przepisywania adresów i usuwa błędy 404 na podstronach.
Zajrzyj do wp-config.php. Stałe WP_HOME i WP_SITEURL nadpisują wartości z bazy, więc dopóki zostaje w nich stary adres, zmiana w wp_options niczego nie da:
define( 'WP_HOME', 'https://nowa-domena.pl' );
define( 'WP_SITEURL', 'https://nowa-domena.pl' );
Ustaw przekierowania ze starej domeny. Przekierowanie stałe 301 przenosi na nową domenę wypracowaną pozycję w wyszukiwarce. Tymczasowe 302 tego nie zrobi.
Multisite to osobna historia
W instalacji wielowitrynowej adresy siedzą dodatkowo w wp_blogs i wp_site, a każda witryna ma własny zestaw tabel z numerem w prefiksie. Zapytania z tego tekstu obejmą wyłącznie witrynę główną. Przy multisite użyj WP-CLI z parametrem --url wskazującym konkretną witrynę.
W jakiej kolejności to robić
Przy przenoszeniu stron klientów trzymam się tej samej kolejności. Najpierw kopia bazy i plików. Potem import na nowy serwer bez dotykania adresów. Dopiero gdy strona odpowiada pod nowym adresem, choćby krzywo, robię zamianę przebiegiem próbnym i sprawdzam liczbę trafień.
Zero trafień znaczy, że adres w bazie zapisany jest inaczej, niż zakładam — najczęściej z http:// zamiast https:// albo z przedrostkiem www.
Trzy pytania, które i tak padną
Czy da się to zrobić bez dostępu do bazy? Tak, wtyczką Better Search Replace z poziomu kokpitu. Ma tryb podglądu, który pokazuje liczbę zmian przed ich wykonaniem, i poprawnie obsługuje dane serializowane.
Dlaczego po zmianie adresu widzę błąd 404 na podstronach? Reguły przepisywania adresów zostały zapisane dla starej domeny. Wejdź w Ustawienia, Bezpośrednie odnośniki i kliknij Zapisz — to je przebuduje.
Czy trzeba zmieniać adresy w plikach motywu?
Zwykle nie, o ile motyw buduje odnośniki funkcjami WordPressa. Sprawdź header.php i functions.php pod kątem adresów wpisanych na sztywno, bo zamiana w bazie ich nie obejmie. W motywach pisanych od zera tego problemu nie ma, bo adresy budowane są funkcjami od początku.
Migracja to moment, w którym najłatwiej coś przeoczyć, a skutki wychodzą tygodniami. Zrób kopię bazy przed zamianą, użyj WP-CLI zamiast surowego SQL-a i przejdź listę z góry, zanim uznasz przeprowadzkę za zakończoną.