后台:我下载了我的WordPress网站数据库的 * .sql 备份,并将旧数据库表前缀的所有实例替换为新的(例如来自默认wp_
类似于asdfghjkl_
)。
我刚刚了解到WordPress在数据库中使用了序列化的PHP字符串,而我所做的将与序列化字符串长度的完整性混淆。
问题是,我在了解此之前删除了备份文件(因为我的网站仍然正常运行),并且安装了许多插件。所以,我无法回复,因此我想知道两件事:
如果可能,我该如何解决这个问题?
这会导致什么样的问题?
(This article声称,例如,WordPress博客可能会丢失其设置和小部件。但这似乎并没有发生在我身上,因为我博客的所有设置仍然完好无损。但我有没有任何关于内部可能被打破的线索,或者未来会出现什么问题。因此这个问题。)
答案 0 :(得分:15)
访问此页面:http://unserialize.onlinephpfunctions.com/
在该页面上,您应该看到此示例序列化字符串:a:1:{s:4:"Test";s:17:"unserialize here!";}
。拿一块它 - s:4:"Test";
。这意味着“字符串”,4个字符,然后是实际的字符串。我很确定你做了什么导致数字字符计数与字符串不同步。使用上述网站上的工具进行播放,例如,如果将“测试”更改为“测试”,您将看到错误。
您需要做的是获取与新字符串匹配的字符数。如果您没有损坏任何其他编码 - 删除冒号或其他东西 - 应该解决问题。
答案 1 :(得分:9)
在尝试将域名从localhost更改为真实URL后,我遇到了同样的问题。经过一番搜索后,我在Wordpress文档中找到了答案:
https://codex.wordpress.org/Moving_WordPress
我会引用那里写的内容:
要避免序列化问题,您有三个选择:
- 如果可以,请使用更好的搜索替换或Velvet Blues更新网址插件。访问您的仪表板。
- 如果您的托管服务提供商(或您)安装了WP-CLI,请使用WP-CLI的搜索替换。
- 在数据库上手动运行搜索并替换查询。注意:仅在wp_posts表上执行搜索和替换。
我最终使用WP-CLI,它可以替换数据库中的内容而不会破坏序列化:http://wp-cli.org/commands/search-replace/
答案 2 :(得分:3)
我知道这是一个老问题,但我认为迟到总比没有好。在继承了在序列化数据上执行了find / 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!
}
}
对我的更改有点令人讨厌的解释:
希望这可以帮助别人...花了近20个小时,包括研究和处理奇怪的问题! :)
答案 3 :(得分:1)
如果错误是由于字符串的长度不正确(我经常看到的),那么您应该能够调整此脚本来修复它:
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);
}
}
}
}
答案 4 :(得分:1)
我个人不喜欢在PHP中工作,或者将我的数据库凭据放在公共文件中。我创建了一个ruby脚本来修复可以在本地运行的序列化:
https://github.com/wsizoo/wordpress-fix-serialization
上下文编辑: 我通过首先通过正则表达式识别序列化,然后重新计算包含的数据字符串的字节大小来处理修复序列化。
$content_to_fix.gsub!(/s:([0-9]+):\"((.|\n)*?)\";/) {"s:#{$2.bytesize}:\"#{$2}\";"}
然后我通过转义的sql更新查询更新指定的数据。
escaped_fix_content = client.escape($fixed_content)
query = client.query("UPDATE #{$table} SET #{$column} = '#{escaped_fix_content}' WHERE #{$column_identifier} LIKE '#{$column_identifier_value}'")
答案 5 :(得分:1)
这个脚本(https://interconnectit.com/products/search-and-replace-for-wordpress-databases/)可以帮助在任何地方使用正确的URL更新sql数据库,而不会遇到序列化的数据问题,因为它会更新“字符数”,这可能会在序列化数据时使您的URL不同步发生。
步骤如下:
如果您已经导入了混乱的数据库(小部件没有 工作,主题选项不存在,等),只需删除该数据库 使用PhpMyAdmin。也就是说,删除它上面的所有内容。然后导出和 手头有一个未经编辑的旧数据库转储。
现在你必须将(未经编辑的)旧数据库导入到 新创建的。您可以通过导入或复制来完成此操作 来自PhpMyAdmin的数据库。请注意,到目前为止,我们还没有做过 搜索和替换;我们只有一个旧的数据库内容和 使用自己的用户和密码将结构转换为新数据库。此时您的网站可能无法访问。
这应该正确更新您的数据库,没有任何序列化数据问题:新URL将在任何地方设置,并且序列化数据字符计数将相应更新。
小部件将被传递,主题设置也是 - 在WordPress中使用序列化数据的两个典型位置。
完成并经过测试的解决方案!