Из-за чего такое может быть с unserialize?


lutskboy
181

Приветствую

Переношу форум с одного сервера на другой

там в некоторых полях данные хранятся в serialize массиве

и на новом сервере при unserialize получаю false

я смотрю на ету строку и там примерно такое

a:9:{s:11:"description";s:10:"Обсуждение";s:15:"additional_data";s:0:"";s:16:"informationTitle";s:0:"";s:15:"informationText";s:0:"";s:9:"rulesText";s:0:"";s:8:"newTopic";b:0;s:9:"readTopic";b:0;s:11:"replicTopic";b:0;s:8:"viewTree";a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}}

если присмотреться то видим s:10:»Обсуждение»;

но слово «Обсуждение» тут должно содержать точно не s:10. 

s:20 для русских символов

как из етого массива сделать нормальный?

и почему там s:10?

или ошибка не в етом?


totamon

возможно разная кодировка бд, таблиц или текстового поля?


timo-71

lutskboy :
если присмотреться то видим s:10:»Обсуждение»;

Норм, для cp1251.

5 минут:

<?php

$o = 'a:9:{s:11:"description";s:10:"Обсуждение";s:15:"additional_data";s:0:"";s:16:"informationTitle";s:0:"";s:15:"informationText";s:0:"";s:9:"rulesText";s:0:"";s:8:"newTopic";b:0;s:9:"readTopic";b:0;s:11:"replicTopic";b:0;s:8:"viewTree";a:5:{i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;}}';
header('Content-Type:text/plain');
function _f(&$a){
    foreach($a as $k=>$v) {
        if(is_array($v)){
            $a[$k] = _f($v);
        } else {
            $a[$k] = is_string($v) ? $o = iconv ( 'cp1251' , 'utf-8' , $v ) : $v;
        }
    }
}
try {
    $o = iconv ( 'utf-8' , 'cp1251' , $o );
    $o =  unserialize($o);
    print_r($o);
    _f($o);
    print_r($o);

} catch (Exception $e) {
    echo $e->getMessage(), "n";
}


exit();

Результат:

Array
(
    [description] => ����������
    [additional_data] =>
    [informationTitle] =>
    [informationText] =>
    [rulesText] =>
    [newTopic] =>
    [readTopic] =>
    [replicTopic] =>
    [viewTree] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
            [4] => 5
        )

)
Array
(
    [description] => Обсуждение
    [additional_data] =>
    [informationTitle] =>
    [informationText] =>
    [rulesText] =>
    [newTopic] =>
    [readTopic] =>
    [replicTopic] =>
    [viewTree] =>
)

Но, надо заранее знать, что «серили» (а как еще это назвать, когда json)  в цп1251🤣


HelgaBorjoni

https://gist.github.com/blessdyb/2b2f31a24e34f2c8da3733d49863c750

Эта функция подойдет.

PHP unserialize utf8 fix
PHP unserialize utf8 fix

  • gist.github.com
PHP unserialize utf8 fix. GitHub Gist: instantly share code, notes, and snippets.


lutskboy

всем спасибо. буду разбираться


timo-71

HelgaBorjoni #:
Эта функция подойдет.
function mb_unserialize($string) {
    $string = preg_replace('!s:(d+):"(.*?)";!se', "'s:'.strlen('$2').':"$2";'", $string);
    return unserialize($string);
}

С доработками для php 7+ в виде preg_replace_callback().


jkm

!s:(d+):"(.*?)";!s

Эта регулярка просто ищёт ближайшую кавычку за которой следует точка с запятой. Всё сломается если в самом тексте встретится эта последовательность.

$str="какой-то "текст"; ещё текст";
$str = serialize($str);

echo $str, "n";

preg_match('!s:(d+):"(.*?)";!s', $str, $match);

echo $match[0], "n";

Результат:

s:47:"какой-то "текст"; ещё текст";
s:47:"какой-то "текст";

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *