Как правильно сменить домен WordPress, ошибка 90% вебмастеров

В Сети куча статей о смене домена WP-сайта, в т.ч. и о переносе WP с локалхоста на сервер, когда девелоперский домен меняется на реальный. И лишь в единицах источников упоминается о том, что бывают сериализованные данные, в которых замена текста first-domain.ru на second-domain.ru равнозначна удалению этих данных. Но даже в тех статьях, где упомянута сия оказия (в частности, на Хабре), не указан способ автоматизировать задачу, кроме как выполнить «аккуратную» (читай — ручную) замену. Хочу поделиться своими успехами в автоматизации правильной смены домена у сайта на WordPress.

Коротко суть проблемы. Многие вебмастеры заблуждаются, говоря, что в смене домена WP нет ничего сложного — достаточно найти и заменить в дампе БД (файл sql) старый домен на новый. И они уверены, что правы, потому что делали так, и всё было норм.

А бывает иначе. В БД удобно хранить данные в сериализованном виде, потому что можно записать массив или объект строкой. Вот конкретный пример части сериализованных данных:

s:8:"base_url";s:17:"http://domain.ru/";

Расшифрую выделенное жирным: s — строковый тип, 17 — число символов, http://domain.ru/ — сами данные. И можно догадаться, что если тут заменить domain на new-domain, то получится что-то не то (ведь в строке http://new-domain.ru/ уже не 17, а 21 символ). А точнее, весь массив будет для программы повреждёнными нечитаемыми данными.

Согласен, обычно проблем не возникает, потому что многие разработчики плагинов и тем оформления предпочитают узнавать URL сайта вызовом get_option('siteurl') и абсолютный путь — из константы ABSPATH. Но мир ведь не без гениев! Вот конкретный пример. У меня сейчас сайт на переносе, и длина его нового доменного имени отличается от старого. Использую такое регулярное выражение в notepad++ для поиска по дампу БД интересующих меня данных:

s:[\d]+:"[^"]*domain\.ru

Где вместо domain.ru подразумевается конкретный домен.

poisk-regulyarnogo-vyirazheniya

И я вижу 90 вхождений! Т.е. все эти данные могли бы потеряться, воспользуйся я простой заменой текста. Для грамотной автоматической замены я написал такой скрипт:

$delta = 1;
$s = file_get_contents( '1.sql' );
$s = preg_replace_callback(
	'~s:([\d]+):"([^"]*)first\.ru~',
	function ($m) {
		global $delta;
		return 's:'.( $m[1]+$delta ).':"'.$m[2].'second.ru';
	},
	$s
);
file_put_contents( '2.sql', $s );

В коде гипотетический домен first.ru заменяется на second.ru. И т.к. разница в их длинах составляет 1 символ, то $delta = 1 (если новый домен у вас будет короче, то разница будет отрицательной). Скрипт читает файл 1.sql и записывает результат в 2.sql. В результате будет заменён не только домен, но и скорректировано значение длины строки, в которой этот домен упомянут.

Кстати, перед заменой обратите внимание, участвует ли домен в абсолютном пути на старом и новом сервере. Иногда бывает, что на старом сервере домен был в абсолютном пути, например:

/home/httpd/vhosts/domen.ru/httpdocs

А на новом сервере домена в пути нет (реальный пример на популярном хостинге СпайсВеб):

/home/m/mebelmakm/maks/public_html

Из примера ясно, что процедуру замены домена в дампе БД надо проводить в 4 этапа:

  • найти и заменить старый абсолютный путь на новый с учётом возможного присутствия его в сериализованных данных (т.е. моим скриптом, например);
  • моим скриптом заменить старое доменное имя на новое;
  • заменить в notepad++ оставшиеся вхождения абсолютного пути (которые в обычных данных — их скрипт не затронул);
  • заменить в notepad++ оставшиеся вхождения старого домена.

По идее, можно допилить мой скрипт, сделать из него плагин WP, который будет принимать на входе строки: старый путь на сервере, новый путь, старый домен, новый домен — и на выходе выгружать дамп БД, готовый для загрузки на новый сервер. Только мне приятней, если юзер обращается за переносом WP сразу ко мне, а не после того, как он своими силами и самопальными плагинами уже поломал свой сайт. :)

Да, когда закончили с дампом БД, надо пройтись регуляркой и обычным поиском по файлам движка (темы оформления, плагины и всё остальное до кучи) — там тоже иногда можно найти вхождения абсолютного пути и домена, иногда даже в сериализованном виде. Пусть и ламер тот кодер, который пишет таким образом темы и плагины, но при переносе WP именно вы отвечаете за дальнейшую работоспособность сайта и должны быть готовы к любому маразму.

Ну, а остальные сведения о смене домена и переносе WP очевидны и описаны в сотнях статей даже на кулинарных сайтах домохозяек в специальной рубрике по обмену постами.

Запись опубликована в рубрике Web-мастеринг с метками . Короткая ссылка для добавления в закладки: Как правильно сменить домен WordPress, ошибка 90% вебмастеров.

3 Responses

  1. andi говорит:

    Перенос осуществить не столько сложно, сколько нужно делать это внимательно.

    Над плагином думал, и примерно те же выводы сделал. Нельзя заранее предсказать, кто и как решит сохранять домен/пути. Стандартная сериализация хорошо, но есть ещё json_encode (не встречал, но почему бы и нет?), зипование + base64, да и ещё фиг знает, что.

    В простейшем случае в 2 этапа колдую над данными:

    1. замена старых серверный путей новыми;

    2. замена старого домена новым.

    По аналогии с имеющимся кодом, можно дополнить скрипт, чтобы сперва пути заменял, а после — домены.

    И ещё, можно ввести пару переменных + дельту на автовычисление подвесить:

    $old_domain = 'first.ru'; $new_domain = 'second.ru'; $delta = strlen($new_domain) - strlen($old_domain);

    Остаётся открытым лишь вопрос работы с puny-доменами, .рф иже с ними. Но тут проще сразу к знающему обратиться, чем запороть дамп и обратиться после.

    • Павлуха говорит:

      Да, внимательность важна. Потому переносы планирую на утро — голова свежая и трафик минимальный. Про json_encode не думал. По идее, с ним проще, чем serialize — та же возможность передать разнотипные данные строкой, но нет заморочки с фиксированными длинами.

      А про puny думал, но забыл. :) Они, действительно, в серверных путях обязательно XN, а в текстах можно и РФ. Короче, либерализацией национальных символов только больше всё запутали. Latinitsa norm!

      • andi говорит:

        Для жителей этой страны было вообще шикарно: смесь букв/цифр(точка)буквы = домен. Сейчас же учитывать нужно и puny в доменах, и QP в путях. Весело, в общем. Маркетологи заскучать не дают)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Иногда ваш комментарий может не отобразиться сразу после публикации - будто пропал. Не волнуйтесь, он не пропадёт и появится потом, после моего одобрения.