php unserialize error notice [duplicate]

Это означает, что указанная переменная не указана ни на что. Я мог бы сгенерировать это так:

SqlConnection connection = null;
connection.Open();

Это вызовет ошибку, потому что, пока я объявил переменную «connection», она не указала ни на что. Когда я пытаюсь вызвать член «Open», для его устранения нет ссылки, и он будет вызывать ошибку.

Чтобы избежать этой ошибки:

  1. Всегда инициализируйте свои объекты, прежде чем пытаться что-либо с ними делать.
  2. Если вы не уверены, что объект имеет значение null, проверьте его с помощью object == null.

Инструмент Resharper JetBrains определит каждое место в вашем коде, которое имеет возможность ошибки нулевой ссылки, позволяя вам ввести нулевую проверку. Эта ошибка является источником ошибок номер один, IMHO.

25
задан FFish 17 May 2010 в 23:52
поделиться

13 ответов

Причина, по которой unserialize() терпит неудачу:

$ser = 'a:2:{i:0;s:5:"héllö";i:1;s:5:"wörld";}';

Это потому, что длина для héllö и wörld неверна, поскольку PHP неправильно обрабатывает многобайтные строки изначально:

echo strlen('héllö'); // 7
echo strlen('wörld'); // 6

Однако, если вы попытаетесь unserialize() получить следующую правильную строку:

$ser = 'a:2:{i:0;s:7:"héllö";i:1;s:6:"wörld";}';

echo '<pre>';
print_r(unserialize($ser));
echo '</pre>';

Это работает:

Array
(
    [0] => héllö
    [1] => wörld
)

Если вы используете PHP serialize() он должен правильно вычислять длины многобайтовых индексов строк.

С другой стороны, если вы хотите работать с сериализованными данными на нескольких (программируемых) языках, вы должны забыть об этом и перейти к чему-то как JSON, который более стандартизирован.

47
ответ дан Alix Axel 25 August 2018 в 16:33
поделиться
  • 1
    большое объяснение Alix, A ++ – FFish 18 May 2010 в 00:43
  • 2
    хороший улов, я забыл, что это может быть UTF-8 – Artefacto 18 May 2010 в 00:50
  • 3
    json_encode: & quot; Эта функция работает только с кодированными данными UTF-8 ... & quot; php.net/manual/en/function.json-encode.php – giorgio79 26 June 2012 в 21:09
  • 4
    @ giorgio79: Да, и ваша точка ...? – Alix Axel 26 June 2012 в 21:35
  • 5
    и в случае, когда вы используете serialize () и unserialize (), все еще не удается, проверьте свой носитель. т. е. mysql, вы должны хранить как двоичные или blob. Если вы храните текст в mysql, он не будет обрабатывать ваши многобайтовые символы. – Dev Null 25 March 2016 в 20:15

Я бы посоветовал использовать javascript для кодирования как json, а затем использовать json_decode для unserialize.

0
ответ дан Artefacto 25 August 2018 в 16:33
поделиться
  • 1
    ага, отличный совет. Надеюсь, он работает с этими чертовыми персонажами. – FFish 18 May 2010 в 00:00
  • 2
    что: $ ser = 'a: 2: {i: 0; s: 5: "héllö"; i: 1; s: 5: "wörld";}; var_dump (десериализации ($ сер)); отлично работает со мной. Что вы подразумеваете под провалом? Не удалось выполнить вызов unserialize ()? – Artefacto 18 May 2010 в 00:01
  • 3
    это дает мне: bool (false) – FFish 18 May 2010 в 00:17

Lionel Chan ответ изменен для работы с PHP> = 5.5:

function mb_unserialize($string) {
    $string2 = preg_replace_callback(
        '!s:(\d+):"(.*?)";!s',
        function($m){
            $len = strlen($m[2]);
            $result = "s:$len:\"{$m[2]}\";";
            return $result;

        },
        $string);
    return unserialize($string2);
}    

Этот код использует preg_replace_callback как preg_replace с помощью / e устаревший с PHP 5.5.

20
ответ дан David 25 August 2018 в 16:33
поделиться
  • 1
    Я должен был использовать эту версию, чтобы помешать HTML-строкам в закодированных массивах получить неверные экранированные двойные кавычки в несериализованных строках. – fideloper 2 November 2015 в 15:46
  • 2
    Отлично, спасибо. – Ryan Szrama 17 February 2016 в 04:55
  • 3
    Миллион благодаря @David. Я уже много дней пытаюсь преобразовать эту функцию! – Ifedi Okonkwo 27 November 2017 в 15:55

Проблема - , как указано Alix - связанной с кодировкой.

До PHP 5.4 внутренняя кодировка для PHP была ISO-8859-1, эта кодировка использует один байт для некоторых символов, которые в юникоде являются многобайтными. В результате многобайтовые значения, сериализованные в системе UTF-8, не будут читаться в системах ISO-8859-1.

Во избежание подобных проблем убедитесь, что все системы используют одну и ту же кодировку:

mb_internal_encoding('utf-8');
$arr = array('foo' => 'bár');
$buf = serialize($arr);

Вы можете использовать utf8_(encode|decode) для очистки:

// Set system encoding to iso-8859-1
mb_internal_encoding('iso-8859-1');
$arr = unserialize(utf8_encode($serialized));
print_r($arr);
8
ответ дан j0k 25 August 2018 в 16:33
поделиться

В ответ на @Lionel выше, фактически, функция mb_unserialize (), которую вы предложили, не будет работать, если сама сериализованная строка содержит последовательность символов "; (цитата, за которой следует точка с запятой). Используйте с осторожностью. Например:

$test = 'test";string'; 
// $test is now 's:12:"test";string";'
$string = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $test);
print $string; 
// output: s:4:"test";string";  (Wrong!!)

JSON - это способы, как упоминалось другими, IMHO

Примечание: я отправляю это как новый ответ, поскольку я не знаю, как ответить напрямую (новый здесь).

2
ответ дан Joe Hong 25 August 2018 в 16:33
поделиться
  • 1
    Вы скоро сможете ответить комментариями. Продолжайте вносить свой вклад! Приветствия ~ – Andrew Kozak 2 April 2012 в 16:36

Я знаю, что это было опубликовано, как год назад, но у меня есть эта проблема, и я столкнулся с этим, и на самом деле я нашел для нее решение. Этот фрагмент кода работает как прелесть!

Идея проста. Это просто помогает вам, пересчитывая длину многобайтовых строк, как указано в @Alix выше.

Несколько модификаций должны соответствовать вашему коду:

/**
 * Mulit-byte Unserialize
 *
 * UTF-8 will screw up a serialized string
 *
 * @access private
 * @param string
 * @return string
 */
function mb_unserialize($string) {
    $string = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $string);
    return unserialize($string);
}

Источник: http : //snippets.dzone.com/posts/show/6592

Протестировано на моей машине, и оно работает как шарм !!

48
ответ дан Lionel Chan 25 August 2018 в 16:33
поделиться
  • 1
    Прекрасно, решила проблему для меня отлично. Благодаря! – mire 16 May 2011 в 16:19
  • 2
    Отлично, спасибо за обмен! Хорошее решение. – Gergely Orosz 21 August 2011 в 20:46
  • 3
    в моем случае проблема была в кодировке базы данных, поэтому я потерял часть своих данных в ???, но эта функция помогает мне сделать работу кода даже с этим, спасибо – llamerr 27 April 2012 в 11:37
  • 4
    Просто спасла мне массивную головную боль! Благодарю. – Damien Roche 4 December 2012 в 20:44
  • 5
    Я опубликовал ниже вашу функцию, измененную для работы с PHP 5.5. Спасибо за ваш полезный вклад. – David 13 January 2015 в 15:32

Еще одно небольшое изменение здесь, которое, надеюсь, поможет кому-то ... Я сериализую массив, а затем записываю его в базу данных. При извлечении данных произошла сбой операции без операции.

Оказывается, что поле longtext базы данных, в которое я писал, использовало latin1, а не UTF8. Когда я включил его, все работало, как и планировалось.

Спасибо всем, кто упомянул кодировку символов и получил меня на правильном пути!

1
ответ дан Mike 25 August 2018 в 16:33
поделиться

этот работал для меня.

function mb_unserialize($string) {
    $string = mb_convert_encoding($string, "UTF-8", mb_detect_encoding($string, "UTF-8, ISO-8859-1, ISO-8859-15", true));
    $string = preg_replace_callback(
        '/s:([0-9]+):"(.*?)";/',
        function ($match) {
            return "s:".strlen($match[2]).":\"".$match[2]."\";"; 
        },
        $string
    );
    return unserialize($string);
}
0
ответ дан Paolo Josef Abadesco 25 August 2018 в 16:33
поделиться
/**
 * MULIT-BYTE UNSERIALIZE
 *
 * UTF-8 will screw up a serialized string
 *
 * @param string
 * @return string
 */
function mb_unserialize($string) {
    $string = preg_replace_callback('/!s:(\d+):"(.*?)";!se/', function($matches) { return 's:'.strlen($matches[1]).':"'.$matches[1].'";'; }, $string);
    return unserialize($string);
}
-1
ответ дан Rogério Agostini 25 August 2018 в 16:33
поделиться

мы можем разбить строку на массив:

$finalArray = array();
$nodeArr = explode('&', $_POST['formData']);

foreach($nodeArr as $value){
    $childArr = explode('=', $value);
    $finalArray[$childArr[0]] = $childArr[1];
}
0
ответ дан Rondip 25 August 2018 в 16:33
поделиться

Сериализация:

foreach ($income_data as $key => &$value)
{
    $value = urlencode($value);
}
$data_str = serialize($income_data);

Unserialize:

$data = unserialize($data_str);
foreach ($data as $key => &$value)
{
    $value = urldecode($value);
}
0
ответ дан sNICkerssss 25 August 2018 в 16:33
поделиться

Не используйте сериализацию / несериализацию PHP, когда другой конец не является PHP. Он не предназначен для портативного формата - например, он даже включает символы ascii-1 для защищенных ключей, с которыми вы не хотите работать в javascript (хотя это будет работать отлично, это просто очень уродливо).

Вместо этого используйте портативный формат, например JSON . XML тоже будет работать, но JSON имеет меньше накладных расходов и более удобен для программистов, так как вы можете легко проанализировать его в простой структуре данных, а не иметь дело с деревьями XPath, DOM и т. Д.

1
ответ дан ThiefMaster 25 August 2018 в 16:33
поделиться
  • 1
    Не говоря уже о неэтериализации из ненадежных источников, это может привести к произвольному выполнению кода. – L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 18 May 2010 в 00:35

В моем случае проблема была связана с окончанием строки (вероятно, какой-то редактор изменил мой файл с DOS на Unix).

Я собрал эти аппартивные обертки:

function unserialize_fetchError($original, &$unserialized, &$errorMsg) {
    $unserialized = @unserialize($original);
    $errorMsg = error_get_last()['message'];
    return ( $unserialized !== false || $original == 'b:0;' );  // "$original == serialize(false)" is a good serialization even if deserialization actually returns false
}

function unserialize_checkAllLineEndings($original, &$unserialized, &$errorMsg, &$lineEndings) {
    if ( unserialize_fetchError($original, $unserialized, $errorMsg) ) {
        $lineEndings = 'unchanged';
        return true;
    } elseif ( unserialize_fetchError(str_replace("\n", "\n\r", $original), $unserialized, $errorMsg) ) {
        $lineEndings = '\n to \n\r';
        return true;
    } elseif ( unserialize_fetchError(str_replace("\n\r", "\n", $original), $unserialized, $errorMsg) ) {
        $lineEndings = '\n\r to \n';
        return true;
    } elseif ( unserialize_fetchError(str_replace("\r\n", "\n", $original), $unserialized, $errorMsg) ) {
        $lineEndings = '\r\n to \n';
        return true;
    } //else
    return false;
}
0
ответ дан Vittorio Zamparella 25 August 2018 в 16:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: