sintax - ¿Se corrigieron los datos serializados rotos debido a la edición de la base de datos MySQL en un editor de texto?
importar base de datos phpmyadmin grande (6)
Visite esta página: http://unserialize.onlinephpfunctions.com/
En esa página, debería ver esta serie serializada de muestra: a:1:{s:4:"Test";s:17:"unserialize here!";}
. Tome un pedazo de él s:4:"Test";
. Eso significa "cadena", 4 caracteres, luego la cadena real. Estoy bastante seguro de que lo que ha hecho se debe a que el número de caracteres numéricos no está sincronizado con la cadena. Juega con la herramienta en el sitio mencionado anteriormente y verás que obtienes un error si cambias "Test" por "Tes", por ejemplo.
Lo que necesita hacer es obtener el recuento de caracteres para que coincida con su nueva cadena. Si no ha dañado ninguna de las otras codificaciones, eliminó dos puntos o algo así, eso debería solucionar el problema.
Antecedentes: descargué una copia de seguridad * .sql de la base de datos de mi sitio de WordPress y reemplacé todas las instancias del prefijo anterior de la tabla de base de datos por una nueva (por ejemplo, desde el wp_
predeterminado a algo como asdfghjkl_
).
Acabo de enterarme de que WordPress usa series de PHP serializadas en la base de datos, y lo que hice se ha metido en la integridad de las longitudes de cadena serializadas.
La cuestión es que eliminé el archivo de copia de seguridad justo antes de enterarme de esto (ya que mi sitio web seguía funcionando bien) e instalé varios complementos desde entonces. Por lo tanto, no hay forma de que pueda revertir y, por lo tanto, me gustaría saber dos cosas:
¿Cómo puedo solucionar esto, si es posible?
¿Qué tipo de problemas podría causar esto?
( Este artículo establece que, por ejemplo, un blog de WordPress podría perder su configuración y widgets. Pero esto no parece haberme pasado, ya que todas las configuraciones de mi blog aún están intactas. Pero no tengo idea de qué podría estar roto en el interior, o qué problemas plantearía en el futuro. De ahí esta pregunta).
Pruebe esta secuencia de comandos que soluciona los problemas de serialización:
Llegué a este mismo problema después de tratar de cambiar el dominio de localhost a la URL real. Después de buscar, encontré la respuesta en la documentación de Wordpress:
https://codex.wordpress.org/Moving_WordPress
Citaré lo que está escrito allí:
Para evitar ese problema de serialización, tiene tres opciones:
- Utilice los complementos de URL de actualización de Better Search Replace o Velvet Blues si puede> acceder a su Dashboard.
- Utilice el reemplazo de búsqueda de WP-CLI si su proveedor de alojamiento (o usted) ha instalado WP-CLI.
- Ejecute una búsqueda y reemplace la consulta manualmente en su base de datos. Nota: solo realice una búsqueda y reemplácela en la tabla wp_posts.
Terminé usando WP-CLI, que es capaz de reemplazar cosas en la base de datos sin romper la serialización: http://wp-cli.org/commands/search-replace/
Si el error se debe a que la longitud de las cadenas es incorrecta (algo que he visto con frecuencia), entonces debería poder adaptar esta secuencia de comandos para solucionarlo:
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);
}
}
}
}
Sé que esta es una vieja pregunta, pero mejor tarde que nunca, supongo. Me encontré con este problema recientemente, después de heredar una base de datos que tenía un find / replace ejecutado en datos serializados. Después de muchas horas de investigación, descubrí que esto se debía a que los conteos de cuerdas estaban desactivados. Desafortunadamente, había demasiados datos con muchos escapes y nuevas líneas y no sabía cómo contar en algunos casos y tenía tantos datos que necesitaba algo automatizado.
En el camino, tropecé con esta pregunta y la publicación de Benubird ayudó a ponerme en el camino correcto. Su código de ejemplo no funcionaba en el uso de producción en datos complejos, contenía numerosos caracteres especiales y HTML, con niveles muy profundos de anidamiento, y no manejaba adecuadamente ciertos caracteres escapados y la codificación. Así que lo modifiqué un poco y pasé incontables horas trabajando en errores adicionales para que mi versión "arreglara" los datos serializados.
// 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!
}
}
Una pequeña explicación geek sobre mis cambios:
- Descubrí que tratar de contar con el código de Benubird como base era demasiado impreciso para grandes conjuntos de datos, así que terminé usando serializar para asegurarme de que el conteo fuera exacto.
- Evité el try / catch porque, en mi caso, la prueba tendría éxito pero acaba de devolver una cadena vacía. Por lo tanto, verifico si hay datos vacíos.
- Intenté varias expresiones regulares, pero solo una modificación en Benubird podría manejar con precisión todos los casos. Específicamente, tuve que modificar la parte que marcaba el ";" porque coincidiría en CSS como "ancho: 100%; altura: 25px;" y rompió la salida. Entonces, utilicé un lookahead positivo para solo coincidir cuando el ";" estaba fuera del conjunto de comillas dobles.
- Mi caso tenía muchas líneas nuevas, HTML y comillas dobles escapadas, así que tuve que agregar un bloque para limpiar eso.
- Hubo un par de situaciones extrañas donde los datos serían reemplazados incorrectamente por la expresión regular y luego la serialización también lo contaría incorrectamente. No encontré NADA en ningún sitio para ayudar con esto y finalmente pensé que podría estar relacionado con el almacenamiento en caché o algo así y probé a enjuagar el buffer de salida (ob_end_flush ()), lo cual funcionó, ¡gracias a Dios!
Espero que esto ayude a alguien ... Me tomó casi 20 horas, incluida la investigación y el tratamiento de problemas extraños. :)
Personalmente, no me gusta trabajar en PHP ni colocar mis credenciales de base de datos en un archivo público. Creé un script de ruby para arreglar serializaciones que puedes ejecutar localmente:
https://github.com/wsizoo/wordpress-fix-serialization
Editar contexto: me acerqué a la serialización de arreglos identificando primero la serialización a través de expresiones regulares, y luego volviendo a calcular el tamaño de bytes de la cadena de datos contenidos.
$content_to_fix.gsub!(/s:([0-9]+):/"((.|/n)*?)/";/) {"s:#{$2.bytesize}:/"#{$2}/";"}
Luego actualizo los datos especificados a través de una consulta de actualización sql escapada.
escaped_fix_content = client.escape($fixed_content)
query = client.query("UPDATE #{$table} SET #{$column} = ''#{escaped_fix_content}'' WHERE #{$column_identifier} LIKE ''#{$column_identifier_value}''")