Исправить сериализованные данные из-за редактирования базы данных MySQL в текстовом редакторе?
Справочная информация: Я скачал *.в SQL резервное копирование базы данных моего сайта WordPress и замена всех экземпляров старого префикса таблицы базы данных новым (например, по умолчанию wp_
что-то вроде asdfghjkl_
).
Я только что узнал, что WordPress использует сериализованные строки PHP в базе данных, и то, что я сделал, испортило целостность сериализованных длин строк.
дело в том, что я удалил файл резервной копии всего прежде чем я узнал об этом (так как мой сайт все еще функционировал нормально), и установил ряд плагинов с тех пор. Таким образом, я не могу вернуться назад, и поэтому я хотел бы знать две вещи:
Как я могу это исправить, если это вообще возможно?
какие проблемы это может вызвать?
(в этой статье заявляет, что, например, блог WordPress, может потерять свои настройки и виджеты. Но это, похоже, не произошло со мной, так как все настройки для моего блога все еще целы. Но я понятия не имею, что может быть сломано внутри, или какие проблемы это создаст в будущем. Отсюда и этот вопрос.)
7 ответов
посетите эту страницу: http://unserialize.onlinephpfunctions.com/
На этой странице вы должны увидеть этот образец сериализованной строки: a:1:{s:4:"Test";s:17:"unserialize here!";}
. Возьми кусочек ... --1-->. Что означает "строка", 4 символов, то строка. Я уверен, что то, что вы сделали, привело к тому, что количество числовых символов не синхронизировано со строкой. Поиграйте с инструментом на сайте, упомянутом выше, и вы увидите, что получите ошибку, если измените "Test" на "Tes", для образец.
что вам нужно сделать, чтобы получить эти подсчеты символов в соответствии с вашей новой строкой. Если вы не повредили какую-либо другую кодировку-удалили двоеточие или что-то еще-это должно устранить проблему.
Я пришел к этой же проблеме после попытки изменить домен с localhost на реальный URL. После некоторого поиска я нашел ответ в документации Wordpress:
https://codex.wordpress.org/Moving_WordPress
Я процитирую что там написано:
чтобы избежать этой проблемы сериализации, у вас есть три варианта:
- используйте лучший поиск заменить или Velvet Blues обновить URL-адреса плагинов, если вы can > доступ к панели мониторинга.
- используйте поиск WP-CLI-замените, если ваш хостинг-провайдер (или вы) установили WP-CLI.
- запустите поиск и замените запрос вручную в базе данных. Примечание: только выполнять поиск и замена в таблице wp_posts.
Я закончил использование WP-CLI, который может заменить вещи в базе данных без нарушения сериализации:http://wp-cli.org/commands/search-replace/
вместе кстати, я наткнулся на этот вопрос и пост Benubird помог поставить меня на правильный путь. Его пример кода не работал в производственном использовании на сложных данных, содержащих многочисленные специальные символы и HTML, с очень глубокими уровнями вложенности, и он неправильно обрабатывал некоторые экранированные символы и кодировку. Поэтому я немного изменил его и провел бесчисленные часы, работая с дополнительными ошибками, чтобы моя версия "исправила" сериализованные данные.
// do some DB query here
while($res = db_fetch($qry)){
$str = $res->data;
$sCount=1; // don't try to count manually, which can be inaccurate; let serialize do its thing
$newstring = unserialize($str);
if(!$newstring) {
preg_match_all('/s:([0-9]+):"(.*?)"(?=;)/su',$str,$m);
# preg_match_all("/s:([0-9]+):(\"[^\"\\]*(?:\\.[^\"\\]*)*\")(?=;)/u",$str,$m); // alternate: almost works but leave quotes in $m[2] output
# print_r($m); exit;
foreach($m[1] as $k => $len) {
/*** Possibly specific to my case: Spyropress Builder in WordPress ***/
$m_clean = str_replace('\"','"',$m[2][$k]); // convert escaped double quotes so that HTML will render properly
// if newline is present, it will output directly in the HTML
// nl2br won't work here (must find literally; not with double quotes!)
$m_clean = str_replace('\n', '<br />', $m_clean);
$m_clean = nl2br($m_clean); // but we DO need to convert actual newlines also
/*********************************************************************/
if($sCount){
$m_new = $m[0][$k].';'; // we must account for the missing semi-colon not captured in regex!
// NOTE: If we don't flush the buffers, things like <img src="http://whatever" can be replaced with <img src="//whatever" and break the serialize count!!!
ob_end_flush(); // not sure why this is necessary but cost me 5 hours!!
$m_ser = serialize($m_clean);
if($m_new != $m_ser) {
print "Replacing: $m_new\n";
print "With: $m_ser\n";
$str = str_replace($m_new, $m_ser, $str);
}
}
else{
$m_len = (strlen($m[2][$k]) - substr_count($m[2][$k],'\n'));
if($len != $m_len) {
$newstr='s:'.$m_len.':"'.$m[2][$k].'"';
echo "Replacing: {$m[0][$k]}\n";
echo "With: $newstr\n\n";
$str = str_replace($m_new, $newstr, $str);
}
}
}
print_r($str); // this is your FIXED serialized data!! Yay!
}
}
немного странное объяснение о моих изменениях:
- я обнаружил, что попытка подсчета с кодом Benubird в качестве базы данных была слишком неточной для больших наборов данных, поэтому я просто использовал сериализацию, чтобы убедиться, что подсчет был точным.
- Я избежал try / catch, потому что в моем случае попытка будет успешной, но просто вернет пустую строку. Вместо этого я проверяю пустые данные.
- Я пробовал многочисленные regex, но только мод на Benubird будет точно обрабатывать все случаи. В частности, мне пришлось изменить часть, которая проверила";", потому что она будет соответствовать CSS, как "ширина:100%; высота:25px;" и сломал выход. Итак, я использовал положительный lookahead, чтобы соответствовать только тогда, когда ";" был вне набора двойных кавычек.
- в моем случае было много новых строк, HTML и экранированных двойных кавычек, поэтому мне пришлось добавить блок, чтобы очистить его.
- было несколько странных ситуаций, когда данные будут заменены неправильно регулярным выражением, а затем сериализация будет считать его неправильно также. Я ничего не нашел на каких-либо сайтах, чтобы помочь с этим, и, наконец, подумал, что это может быть связано с кэшированием или чем-то подобным, и попытался очистить выходной буфер (ob_end_flush ()), который работал, слава богу!
надеюсь, это кому-то поможет... Заняло у меня почти 20 часов, включая исследования и решение странных проблем! :)
Если ошибка вызвана неправильной длиной строк (что - то я часто видел), то вы должны быть в состоянии адаптировать этот скрипт, чтобы исправить это:
foreach($strings as $key => $str)
{
try {
unserialize($str);
} catch(exception $e) {
preg_match_all('#s:([0-9]+):"([^;]+)"#',$str,$m);
foreach($m[1] as $k => $len) {
if($len != strlen($m[2][$k])) {
$newstr='s:'.strlen($m[2][$k]).':"'.$m[2][$k].'"';
echo "len mismatch: {$m[0][$k]}\n";
echo "should be: $newstr\n\n";
$strings[$key] = str_replace($m[0][$k], $newstr, $str);
}
}
}
}
мне лично не нравится работать в PHP или размещать мои учетные данные БД в общедоступном файле. Я создал скрипт ruby для исправления сериализации, которую вы можете запускать локально:
https://github.com/wsizoo/wordpress-fix-serialization
Контекстное Редактирование: Я подошел к исправлению сериализации, сначала идентифицировав сериализацию через регулярное выражение, а затем пересчитав размер байта содержащейся строки данных.
$content_to_fix.gsub!(/s:([0-9]+):\"((.|\n)*?)\";/) {"s:#{.bytesize}:\"#{}\";"}
затем я обновляю указанные данные через беглый запрос на обновление.
escaped_fix_content = client.escape($fixed_content)
query = client.query("UPDATE #{$table} SET #{$column} = '#{escaped_fix_content}' WHERE #{$column_identifier} LIKE '#{$column_identifier_value}'")
этот скрипт (https://interconnectit.com/products/search-and-replace-for-wordpress-databases/) может помочь обновить базу данных sql с соответствующими URL-адресами везде, не сталкиваясь с проблемами сериализованных данных, потому что она обновит "количество символов", которое может вывести ваши URL-адреса из синхронизации при возникновении сериализованных данных.
шаги будут:
Если вы уже импортировали испорченную базу данных (виджеты не работа, тема опций нет и т. д.), Просто отбросьте эту базу данных использование PhpMyAdmin. То есть удалить все, что на нем. Затем экспорт и имейте под рукой не отредактированный дамп старой базы данных.
теперь вам нужно импортировать (не отредактированную) старую базу данных в только что созданный. Вы можете сделать это с помощью импорта или копирования БД от PhpMyAdmin. Обратите внимание, что до сих пор мы не делали никаких поиск и замена еще; у нас просто есть старый контент базы данных и структура в новый база данных со своим пользователем и паролем. Ваш сайт, вероятно, будет недоступен в этот момент.
- убедитесь, что ваши файлы WordPress недавно загружены в правильная папка на сервере и отредактируйте wp-config.PHP, чтобы сделать это подключитесь к новой базе данных.
- загрузить скрипт в "секретную" папку-просто для безопасности причины-на том же уровне, что и wp-admin, wp-content и wp-includes. Не забудьте удалить все сразу поиск и замена произошла, потому что вы рискуете предложить свои данные БД открыт для всего интернета.
- теперь наведите браузер на секретную папку и используйте скрипт в порядке взаимодействие. Это само собой разумеется. После использования, мы приступаем к полностью удалите его с сервера.
Это должно иметь вашу базу данных должным образом обновлена, без каких-либо проблем сериализованных данных вокруг: новый URL будет установлен везде, и сериализованные данные количество символов будет соответствующим образом обновлено.
виджеты будут переданы, а также настройки темы - Два из типичных мест, которые используют сериализованные данные в WordPress.
готово и протестировано решение!