Как изменить домен для сети сайтов (на примере WordPress)

Владимир | | MySQL, PHP, Web разработка, WordPress.

wordpress multisite move

В этой статье речь пойдет об основных проблемах, которые возникают при переносе сети сайтов с одного домена на другой и, естественно, о том, как их решить.

Сразу хочу сделать небольшое отступление. В большинстве случаев для сайта, к которому открыт публичный доступ, изменение домена является «крайней» мерой. И почти всегда без неё можно обойтись. Тем не менее, бывают ситуации, когда всё-таки лучше изменить адрес сайта, например, если куплен «красивый» домен.

Обычно процесс переноса состоит из следующих этапов:

  1. Перенос кода.
  2. Перенос статики (картинки и т.п.).
  3. Перенос базы данных.

С первыми двумя этапами проблемы возникают редко. Могут, конечно, возникнуть сложности с запуском сайта из-за разницы в настройках серверов, но это отдельная тема. Статические файлы перенести проще всего, в 90% случаев достаточно просто скопировать папку uploads (или аналогичную).

А вот с базой данных ситуация интереснее, т.к. многое зависит от того какая именно информация в ней хранится.

В идеальном случае в базе отсутствует информация, связанная с доменом. Т.е. достаточно просто скопировать базу и всё будет правильно работать.

Но такая ситуация встречается довольно редко. Например, если вы создаёте статьи в какой-нибудь CMS, то практически наверняка в них будут внутренние ссылки. Кроме того, домен может быть указан в таблице опций (WordPress).

В этом случае достаточно перед импортом выполнить поиск/замену доменов в дампе базы.

Ситуация усложняется если информация о домене хранится в сериализованном виде. Такой способ хранения использует WordPress в multisite режиме. С точки зрения разработчика это может быть удобно, т.к. функция serialize преобразовывает PHP объект в строку, которую можно спокойно записать в базу и затем точно так же прочитать и преобразовать в объект.

Но если в этом случае вы попытаетесь использовать поиск/замену, то, скорее всего, получите не работающий сайт. Дело в том, что в сериализованном формате сохраняются не только значения атрибутов объекта, но и их длина. Поэтому если количество символов в новом имени домена отличается от старого, то операция десериализации правильно работать не будет.

Для такой ситуации алгоритм замены домена должен быть примерно таким:

  1. просматриваем по очереди все записи в базе;
  2. если в каком-нибудь поле найдено название старого домена, то:
    1. проверяем, является ли значение этого поля сериализованным объектом, если да, десериализуем его, изменяем значение соответствующего атрибута и снова сериализуем его, если нет – просто изменяем название домена на новое;
    2. сохраняем запись.

Как видите, алгоритм достаточно простой, но самое интересное в том, что код писать в не обязательно 😉
Существует готовый и достаточно удобный скрипт под названием Search Replace DB.

Source

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

searchreplacedb2

Также не стоит забывать, что время работы скрипта зависит от размера базы данных. Поэтому желательно перед выполнением в php.ini установить
max_execution_time = 0

Несмотря на то, что данный скрипт ориентирован преимущественно под WordPress, он неплохо работает и с другими движками. Я использовал его для переноса сетки блогов, работающих на WordPress, а также проекта на Yii фреймворке. В обоих случаях он отработал абсолютно правильно. Также есть информация, что он правильно работает и с другими CMS, например, с Drupal и Joomla. Хотя в любом случае, бэкап базы нужно обязательно сделать.

И внимательно следите, чтобы этот скрипт не оказался на продакшн сервере. Последствия могут быть самыми неприятными.

В заключение приведу небольшой список симптомов, указывающих на неправильный перенос базы.

  1. Кольцевые редиректы.
  2. Не открываются все страницы кроме главной.
  3. Редирект на страницу регистрации нового сайта (для WP).

Также в случае WordPress может отправляться редирект на страницу входа после отправки правильных логина и пароля. В этом случае достаточно удалить cookie.

Успехов!

Интересно почитать:

Если нужно найти человека по номеру мобыльного или по имени и фамилии, то в онлайне есть большая база населения Украины, в том числе мобильный номер и прописка.

Скачать договор безвозмездного пользования транспортным средством под вашу ситуацию

Заполнение деклараций 3-НДФЛ за 2012 на заказ. Результат — по почте

  • Vitaliy Orlov

    Можно без проблем, заменять данные в сериализированной строке, вместе с её длинной.

    Вот пример получения такой строки:

    а дальше можно использовать обычный sql REPLACE, разумеется, надо заменять часть сериализированных данных, вместе с длинной текста:

    Примерно так у меня работает генератор конфигов для WP. Выбираю флажки, он генерит настройки для плагинов, в дамп.

  • Vitaliy Orlov

    парсер съел код:

    function ser_block($text)
    {
        $ret = 's:'
             .strlen(addslashes($text)).':'
             .'»'.addslashes($text).'»;';
        return $ret;
    }

    и пример SQL-а:

    $sql= » UPDATE `table` SET
                `field` = REPLACE( `field`,
                                   's:5:»Hello»;',
                                   '».mysql_real_escape_string( ser_block('Привет') ).»'
                )
    «;

    • Все отлично, но есть ситуации когда вы не знаете заранее в каком поле сериализованные значения.

      • Vitaliy Orlov

        Да, я согласен, что это не всегда подойдет.

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

        Где-то проще, использовать Safe Search Replace, где-то можно обойтись SQL запросами, а где-то придется написать свой костыль.

  • Не совсем в тему, но может вы подскажете, как быть когда есть мультисайт, но для одного из сайтов сети надо сделать основынм доменом не podsite.site.com или site.com/podsite а прикрутить для него свой собсвенный домен?