Почему при импорте базы данных теряются данные текстовых виджетов?
Я создал сайт на WordPress на нашей машине для разработки. В используемой теме есть несколько областей для виджетов для отображения текста (сайдбар и главная страница). Я использовал простые текстовые виджеты во всех этих областях для размещения нашей информации.
При миграции сайта на продакшн я использовал плагин WP-DB-Backup для создания снапшота базы данных. Затем я отредактировал полученный .sql файл, чтобы обновить все пути к файлам и URL-ссылки, указывающие на наш продакшн-сайт.
После создания базы данных, веб-сайта и копирования всех файлов на продакшн-сайт, я запускаю .sql файл из командной строки mysql для импорта данных в новую базу данных.
Однако когда я захожу на продакшн-сайт, часть текста отображается, а часть нет. Когда я проверяю раздел виджетов сайта, текстовые виджеты отсутствуют в некоторых областях виджетов. Текстовые виджеты даже не видны в зоне "Неактивные виджеты", их просто нет.
Я даже попробовал повторить процесс с использованием плагина BackWPup, заметив, что синтаксис SQL отличается при выгрузке базы данных.
Почему я теряю данные текстовых виджетов во время импорта?

Вот в чём ваша проблема:
Затем я отредактировал получившийся .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-адреса.

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

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

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

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

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

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

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

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

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

Для решения этой проблемы я всегда использую инструмент WordPress Serialized Search & Replace, доступный по ссылке. Он работает безупречно и без каких-либо проблем. Я пользуюсь им уже давно для всех задач по миграции сайтов. Этот инструмент отлично справляется с проблемами при переносе базы данных из среды разработки в продакшен.
https://interconnectit.com/search-and-replace-for-wordpress-databases/

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

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

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

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

Ответ Отто совершенно верен. Я тоже столкнулся с этой проблемой на собственном опыте.
Однако мне удалось найти обходное решение с помощью отличного скрипта с сайта http://spectacu.la/search-and-replace-for-wordpress-databases/
Чтобы перенести ваш WordPress на новый URL или домен, выполните следующие действия:
- Сделайте дамп базы данных (например, используя phpMyAdmin) существующего WordPress
- Восстановите дамп без изменений (без модификаций) на новом месте
- Распакуйте скрипт с spectacu.la в корневую папку WordPress (это не плагин...)
- Запустите скрипт на новом сайте, перейдя по соответствующему URL, например http://new-website.url/searchreplacedb.php
- Не забудьте удалить скрипт из корневой папки WordPress после использования

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

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

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

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

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

Я использовал плагин 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, но он всё равно повреждает мои сериализованные данные.
