Почему при импорте базы данных теряются данные текстовых виджетов?

10 февр. 2011 г., 17:35:10
Просмотры: 38.7K
Голосов: 48

Я создал сайт на WordPress на нашей машине для разработки. В используемой теме есть несколько областей для виджетов для отображения текста (сайдбар и главная страница). Я использовал простые текстовые виджеты во всех этих областях для размещения нашей информации.

При миграции сайта на продакшн я использовал плагин WP-DB-Backup для создания снапшота базы данных. Затем я отредактировал полученный .sql файл, чтобы обновить все пути к файлам и URL-ссылки, указывающие на наш продакшн-сайт.

После создания базы данных, веб-сайта и копирования всех файлов на продакшн-сайт, я запускаю .sql файл из командной строки mysql для импорта данных в новую базу данных.

Однако когда я захожу на продакшн-сайт, часть текста отображается, а часть нет. Когда я проверяю раздел виджетов сайта, текстовые виджеты отсутствуют в некоторых областях виджетов. Текстовые виджеты даже не видны в зоне "Неактивные виджеты", их просто нет.

Я даже попробовал повторить процесс с использованием плагина BackWPup, заметив, что синтаксис SQL отличается при выгрузке базы данных.

Почему я теряю данные текстовых виджетов во время импорта?

1
Комментарии

Я провёл небольшое исследование, и единственное, что приходит на ум — информация о виджетах хранится в таблице wp_options, причём некоторые данные кодируются довольно странным образом. Пока что у меня не было возможности проверить это с другой темой, чтобы понять, связано ли это поведение с текущей темой.

Dillie-O Dillie-O
10 февр. 2011 г. 17:39:35
Все ответы на вопрос 5
11
46

Вот в чём ваша проблема:

Затем я отредактировал получившийся .sql-файл, чтобы обновить все пути к файлам и URL-ссылки, указывающие на наш рабочий сайт.

Так делать нельзя. WordPress хранит многие настройки в виде "сериализованных данных", которые содержат как строковое содержимое, так и его длину. Если вы изменяете URL и его длина меняется, то сериализованные данные становятся некорректными, и PHP их отвергает.

Основная проблема в том, что вы делаете это неправильно. Если вы настраиваете сайт для разработки, данные с которого будут переноситься, он изначально должен иметь тот же URL, что и рабочий сайт. Вы можете вручную отредактировать файл HOSTS, чтобы задать для рабочего домена (например, example.com) другой IP-адрес (например, 127.0.0.1), и тогда "рабочий" URL будет вести на сайт для разработки, но только для вас. Таким образом, вы сможете создавать данные, ссылки и всё остальное, используя рабочий URL, и при переносе данных ничего не придётся изменять.

В краткосрочной перспективе, однако, не используйте простой поиск и замену в SQL-файле. Как вы уже убедились, это ломает данные.

И хотя мне не хочется это предлагать, есть способ изменить код ядра WordPress, чтобы он обрабатывал повреждённые сериализованные данные. Вам нужно изменить файл wp-includes/functions.php и изменить функцию maybe_unserialize() следующим образом:

function maybe_unserialize( $original ) {
    if ( is_serialized( $original ) ) {
        $fixed = preg_replace_callback(
            '!(?<=^|;)s:(\d+)(?=:"(.*?)";(?:}|a:|s:|b:|i:|o:|N;))!s',
            'serialize_fix_callback',
            $original );
        return @unserialize( $fixed );
    }
    return $original;
}
function serialize_fix_callback($match) { return 's:' . strlen($match[2]); }  

Это НЕ долгосрочное решение. Оно должно использоваться только для того, чтобы быстро восстановить работоспособность. В долгосрочной перспективе вам нужно исправить процесс разработки, чтобы не приходилось вручную менять URL-адреса.

10 февр. 2011 г. 20:45:26
Комментарии

@Otto отличный ответ. Быстрый вопрос: повлияет ли изменение несериализованной blob/text таблицы, такой как wp_posts, вне MySql на какие-либо сериализованные данные в wp_post_meta или wp_options? У меня была такая же проблема с текстовым виджетом, но я не трогал wp_options, а только изменял wp_posts.

Chris_O Chris_O
10 февр. 2011 г. 21:40:06

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

Dillie-O Dillie-O
10 февр. 2011 г. 22:52:15

Это НЕ жизнеспособное долгосрочное решение. - даже краткосрочное.

hakre hakre
11 февр. 2011 г. 03:18:48

Интересно; как можно отредактировать файл hosts, чтобы перенаправить example.com на localhost 127.0.0.1?

markratledge markratledge
11 февр. 2011 г. 07:28:02

Если вам нужно сделать это на локальной машине, просто найдите файл hosts и добавьте туда запись (проверьте superuser.com для конкретных инструкций под вашу ОС). В противном случае попросите вашего системного или сетевого администратора добавить запись на контроллере домена.

Dillie-O Dillie-O
11 февр. 2011 г. 16:41:50

Другой обходной путь, который используют некоторые, — это присвоить своей разработческой системе доменное имя "example.dev" вместо "example.com". Таким образом, длины строк не изменяются при переносе в продакшен. Я предпочитаю метод с файлом HOSTS.

Otto Otto
11 февр. 2011 г. 23:28:25

@songdogtech - Добавьте новую строку в файл hosts 127.0.0.1 example.com, файл находится по пути C:\WINDOWS\system32\drivers\etc\hosts..(при условии стандартного пути установки). Примечание: Xampp и подобные приложения обычно добавляют виртуальные хосты в этот файл, поэтому там уже могут быть записи.

t31os t31os
12 февр. 2011 г. 11:14:28

Это не совсем решение, а скорее костыль! Также бывают сценарии, когда нельзя изменить файл hosts. Например, за корпоративным прокси или если в production используется https, а в development - http.

grm grm
8 авг. 2012 г. 11:06:05

2016 год, а WordPress до сих пор сохраняет сериализованные данные в базе. Приз за самый известный худший код можно не искать дальше.

Ejaz Ejaz
8 мар. 2016 г. 13:56:26

СПАСИБО!!! Хорошее замечание и отличный хак. Обычно я использую этот хак, чтобы вернуть все данные, а затем просто обновляю существующие настройки снова, и после удаления этого кода всё работает идеально.

Ivijan Stefan Stipić Ivijan Stefan Stipić
4 февр. 2017 г. 11:13:09

Насколько я знаю, wp-cli с использованием "wp db import" должен обрабатывать это по умолчанию, но у меня данные виджетов всё равно не отображаются. Может, я что-то упускаю?

trainoasis trainoasis
21 июн. 2018 г. 15:30:37
Показать остальные 6 комментариев
5
12

Для решения этой проблемы я всегда использую инструмент WordPress Serialized Search & Replace, доступный по ссылке. Он работает безупречно и без каких-либо проблем. Я пользуюсь им уже давно для всех задач по миграции сайтов. Этот инструмент отлично справляется с проблемами при переносе базы данных из среды разработки в продакшен.

https://interconnectit.com/search-and-replace-for-wordpress-databases/

28 мар. 2013 г. 16:07:20
Комментарии

Да, использую этот скрипт уже много лет и очень рекомендую

davemac davemac
5 июн. 2013 г. 01:45:02

У меня обычно работало. Но на этой неделе, когда я заменил http://localhost/Me/site_name на http://site.dev (с одного локального хоста на другой) используя версию 3.0.0, я странным образом потерял позиции виджетов и меню. Возможно, эта проблема также связана с длиной строки.

rhand rhand
27 нояб. 2014 г. 09:01:53

Я использую... но пока не сталкивался с такой ситуацией. Можете скачать более старую версию этого скрипта и попробовать с ней. Попробуйте заменить localhost/Me/site_name на site.dev.

Subharanjan Subharanjan
27 нояб. 2014 г. 12:17:17

URL изменился (теперь https вместо http): https://interconnectit.com/products/search-and-replace-for-wordpress-databases/

Koryonik Koryonik
18 сент. 2015 г. 12:26:25

Потрясающий скрипт. Я скопировал базу данных MySQL через PHPMyAdmin со старой на новую — без каких-либо изменений URL-адресов — затем перешел в папку нового сайта, где находились свежие файлы WordPress (вместе с правильным wp-config.php с новыми учетными данными базы данных), добавил скрипт, и он позаботился обо всем. Сериализованные данные обновляются вместе с обычными URL. Просто и быстро! Очень рекомендую. Важно: не забудьте удалить скрипт после использования, так как у него есть доступ к данным вашей базы данных!

Peanuts Peanuts
8 февр. 2018 г. 03:19:25
4

Ответ Отто совершенно верен. Я тоже столкнулся с этой проблемой на собственном опыте.

Однако мне удалось найти обходное решение с помощью отличного скрипта с сайта http://spectacu.la/search-and-replace-for-wordpress-databases/

Чтобы перенести ваш WordPress на новый URL или домен, выполните следующие действия:

  1. Сделайте дамп базы данных (например, используя phpMyAdmin) существующего WordPress
  2. Восстановите дамп без изменений (без модификаций) на новом месте
  3. Распакуйте скрипт с spectacu.la в корневую папку WordPress (это не плагин...)
  4. Запустите скрипт на новом сайте, перейдя по соответствующему URL, например http://new-website.url/searchreplacedb.php
  5. Не забудьте удалить скрипт из корневой папки WordPress после использования
17 апр. 2011 г. 19:21:25
Комментарии

Я знаю, что это немного устарело, но где я должен указать новое имя базы данных, если я восстанавливаю дамп как есть? Разве мне не следует хотя бы указать новое имя базы данных во втором шаге? Спасибо за эту информацию

andresmijares andresmijares
5 янв. 2012 г. 21:22:12

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

Yoav Aner Yoav Aner
8 янв. 2012 г. 18:45:06

Привет, Yoav, спасибо за ответ. Я имею в виду, что когда я экспортирую БД, я обычно меняю имя базы данных на новое и изменяю ссылки на домен. Учитывая это, в вашем втором шаге вы говорите восстановить дамп как есть, без изменений. Я просто хотел узнать, это буквально или мне все же нужно изменить хотя бы имя базы данных. Я понимаю, что это может быть глупый вопрос, но я немного запутался. Еще раз спасибо за ответ.

andresmijares andresmijares
8 янв. 2012 г. 20:19:38

Я не знаю, как именно вы делаете дамп базы данных, но если используете инструмент 'export' в phpmyadmin, то название базы данных не имеет значения. Вы можете экспортировать базу и импортировать её в любую другую базу данных. В целом, что касается второго пункта списка, я считаю, что изменение имени базы данных - это нормально.

Yoav Aner Yoav Aner
9 янв. 2012 г. 17:09:30
0

Автор вопроса был слишком усерден при выполнении поиска и замены в файле экспорта базы данных, в результате чего изменились вхождения "wp_" в некоторых сериализованных данных. Решение заключается в более аккуратном поиске и замене, включая обратные кавычки в регулярное выражение, а затем вручную обновить оставшиеся ключи в базе данных после импорта.

Если вы переносите сайт и меняете префикс таблиц, и предпочитаете более ручной подход, выполните следующие действия (этот метод решает только проблему автора вопроса и не затрагивает обновление URL сайта):

  1. Создайте резервную копию и переместите файл экспорта базы данных SQL в новую среду (в примере предполагается имя файла backup_YYYY-MM-DD.sql)
  2. Выполните массовый поиск и замену в SQL-файле, чтобы изменить имена таблиц на новый префикс (ПЕРЕД импортом SQL-файла!). Один из способов сделать это — использовать Perl однострочник: perl -p -i.bak -e "s/`wp_/`myprefix_/g" backup_YYYY-MM-DD.sql
  3. Импортируйте SQL-данные в базу данных
  4. Обновите все ключи в таблице _options, содержащие жёстко прописанный префикс: update myprefix_options set option_name = concat('myprefix_',substr(option_name,4)) where option_name like 'wp_%'
  5. Обновите все ключи в таблице _user_meta, содержащие жёстко прописанный префикс: update myprefix_usermeta set meta_key = concat('myprefix_',substr(meta_key,4)) where meta_key like 'wp_%'
24 мая 2011 г. 02:12:52
1

Я использовал плагин WP Migrate, который заменяет http и пути к папкам.

У меня возникла одна проблема при импорте, но я решил её, добавив следующие строки в начало сгенерированного SQL-файла:

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

Я также пробовал инструмент Search And Replace (v2.1), который предложил @Yoav, но он всё равно повреждает мои сериализованные данные.

10 июл. 2012 г. 17:40:08
Комментарии

Привет, Рикардо! Добро пожаловать в WordPress Answers! Раздел, в который вы написали, предназначен для ответов на оригинальный вопрос. Хотя ваш вопрос связан с темой, лучше создать отдельный вопрос. Так у вас будет гораздо больше шансов получить ответ.

Chris_O Chris_O
11 июл. 2012 г. 13:02:20