Что может вызвать сбой в функции сериализации PHP? - PullRequest
2 голосов
/ 27 августа 2009

У меня есть некоторый серверный PHP-код, который пытается сохранить объект данных (по сути, многомерный массив) в серверной базе данных. Этот объект данных изначально поступает как объект действия AMF, отправленный из приложения flex. Я хочу сохранить объект целиком для дальнейшего использования, поэтому я использовал функцию сериализации php и закодировал объект простой строкой, которая может войти в поле базы данных. Код выглядит так:

$serializedDataObject = base64_encode(serialize($objectInstance->myDataObject));

Когда я хочу восстановить этот объект и вернуть его, я просто запускаю реверс

$unserializedDatanObject = unserialize(base64_decode($serializedDataObject));

Пока, похоже, это работает хорошо. Но иногда мой PHP-скрипт не работает. Я думаю, что это не удается на этапе сериализации. Мой вопрос теоретически заключается в том, что может привести к сбою процесса сериализации и кодирования php? Существуют ли определенные символы или виды данных в массиве объектов данных, которые могут привести к сбою сериализации?

Нужно ли выполнять некоторый массаж объекта данных, прежде чем я попытаюсь его сериализовать?

Edit:

Чтобы уточнить, процесс работает следующим образом

У меня есть клиентское приложение Flex / Actionscript, которое отправляет объекты ActionScript на основе AMF на сервер. На стороне PHP я использую библиотеку Zend AMF для чтения данных AMF. Объект может быть проверен в PHP и в основном выглядит как ассоциативный многомерный массив. Именно в этот момент я пытаюсь сериализовать и кодировать с помощью base 64 объект, чтобы сохранить объект в базе данных в виде закодированной строки.

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

Ответы [ 6 ]

5 голосов
/ 27 августа 2009

Ресурсы не могут быть сериализованы, что может быть проблемой. Чтобы избежать этой проблемы, используйте магические методы: __sleep и __wakeup.

По сути, ваша __sleep функция вызывается, когда вы вызываете serialize, а __wakeup - когда вы не сериализуете, так что это соединение с базой данных: в sleep () закройте соединение и сохраните где-нибудь строку соединения (возможно) и при пробуждении переподключитесь.

4 голосов
/ 27 августа 2009

@ Грег прав в том, что вы не можете сериализовать ресурсы.

Учитывая, что вы описываете свои объекты как "объекты данных", у меня есть ощущение, что они содержат ваши ресурсы подключения к базе данных? (например, $object->rs = mysql_connect(...);).

Если это так , рассмотрите возможность использования функций __sleep() и __wakeup() в ваших объектах данных (__sleep() вызывается непосредственно перед сериализацией, __wakeup() сразу после десериализации ).

Функция __sleep() должна закрывать любую базу данных или файловые ресурсы, а функция __wakeup() должна повторно подключаться к базе данных.

В приведенной выше записи руководства PHP приведен пример класса, который управляет подключением к БД, который можно сериализировать:

<?php
class Connection {
    protected $link;
    private $server, $username, $password, $db;

    public function __construct($server, $username, $password, $db)
    {
        $this->server = $server;
        $this->username = $username;
        $this->password = $password;
        $this->db = $db;
        $this->connect();
    }

    private function connect()
    {
        $this->link = mysql_connect($this->server, $this->username, $this->password);
        mysql_select_db($this->db, $this->link);
    }

    public function __sleep()
    {
        return array('server', 'username', 'password', 'db');
    }

    public function __wakeup()
    {
        $this->connect();
    }
}
3 голосов
/ 27 августа 2009

На php.net/bas64_decode есть некоторые упоминания о больших строках, которые плохо декодируются. Кроме того, если у вас есть неподдерживаемые форматы символов в объекте, это может вызвать проблемы.

  1. Убедитесь, что в ваших объектах нет неподдерживаемых форматов символов
  2. Попробуйте и запишите, насколько велики объекты, которые сериализуются
3 голосов
/ 27 августа 2009

Нельзя правильно сериализовать ресурсы, такие как дескрипторы файлов или соединения с базой данных. Вы также не можете сериализовать встроенные объекты PHP, хотя я не совсем уверен, что это покрывает.

1 голос
/ 27 августа 2009

Храните ли вы сериализованные данные в базе данных? Если да, достаточно ли большое поле для хранения данных? Кодировка Base64 увеличивает длину строки примерно в 1,3 раза, которая в некоторых системах БД усекается.

1 голос
/ 27 августа 2009

Должен пойти с Томом на этот; процитировать php.net / сериализовать :

Значение для сериализации. serialize () обрабатывает все типы, кроме типа ресурса. Вы даже можете сериализировать () массивы, которые содержат ссылки на себя. Циркулярные ссылки внутри массива / объекта, который вы сериализуете, также будут сохранены. Любая другая ссылка будет потеряна.

Что касается стандартных объектов, у вас не должно быть проблем. Зарегистрируйте данные, которые вы получаете после base64_encoding / decoding, затем используйте следующую строку для проверки ваших данных.

<code>echo '<pre>'; print_r($decodedObject); echo '
';
...