wiem, jest to stara sprawa, ale lepiej późno niż wcale, jak sądzę. Niedawno pojawił się ten problem, po odziedziczeniu bazy danych, która miała znaleźć/zamień wykonane w serializowanych danych. Po wielu godzinach poszukiwań odkryłem, że dzieje się tak dlatego, że liczby łańcuchów były wyłączone. Niestety, było tak dużo danych z dużą ilością ucieczek i nowych linii i nie wiedziałem, jak liczyć w niektórych przypadkach i miałem tak dużo danych, że potrzebowałem czegoś zautomatyzowanego.
Po drodze natknąłem się na to pytanie, a post Benubird pomógł mi postawić właściwą drogę. Jego przykładowy kod nie działał w produkcji na złożonych danych, zawierających liczne znaki specjalne i HTML, z bardzo głębokimi poziomami zagnieżdżania, i nie obsługiwał poprawnie niektórych znaków i znaków kodowanych. Więc trochę zmodyfikowałem i spędziłem niezliczone godziny, pracując nad dodatkowymi błędami, aby moja wersja mogła "naprawić" zserializowane dane.
// 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!
}
}
Trochę naukowy wyjaśnienie moich zmian:
- Okazało się, że stara się liczyć z kodem Benubird jako baza była zbyt niedokładne dla dużych zbiorów danych, więc skończyło się tylko za pomocą serializacji aby mieć pewność, liczba była dokładna.
- Uniknęłem try/catch, ponieważ w moim przypadku próba się powiodła, ale właśnie zwrócił pusty ciąg znaków. Dlatego zamiast tego sprawdzam puste dane.
- Próbowałem wielu regex, ale tylko mod na Benubird's będzie dokładnie obsługiwać wszystkie przypadki. W szczególności musiałem zmodyfikować część, która została sprawdzona dla ";" ponieważ pasowałoby do CSS, takich jak "width: 100%; height: 25px;" i zepsuł wynik. Więc użyłem pozytywnego uprzedzenia, aby dopasować tylko, gdy ";" był poza zbiorem podwójnych cytatów.
- Moja sprawa zawierała mnóstwo nowych linii, HTML i Escaped podwójnych cytatów, więc musiałem dodać blok, żeby to wyczyścić.
- Było kilka dziwnych sytuacji, w których dane zostałyby niepoprawnie zastąpione przez wyrażenie regularne, a następnie serializacja również zliczyłaby to niepoprawnie. Znalazłem NIC na jakichkolwiek stronach, aby pomóc z tym i na końcu pomyślałem, że może to być związane z buforowaniem lub czymś podobnym i wypróbowane przepłukanie bufora wyjściowego (ob_end_flush()), który działał, dzięki Bogu!
Mam nadzieję, że to pomoże komuś ... Zajęło mi to prawie 20 godzin, włączając w to badania i zajmowanie się dziwnymi sprawami! :)
Dziękuję bardzo. Twoja odpowiedź mi pomogła. @ s_ha_dum –
Dzięki za wyjaśnienie! Po znalezieniu problemów znalazłem ten kod, aby ponownie poprawić serializacje. Sprawdź https://stackoverflow.com/a/38890855/2323296 –