У меня есть некоторый PHP-код на сервере, который пытается сохранить объект данных (по существу, многомерный массив) для базы данных. Этот объект данных первоначально входит как объект ActionScript AMF, отправленный из приложения flex. Я хочу сохранить объект целиком для последующего использования, поэтому я использовал функцию сериализации php и закодировал объект по простой строке, которая может попасть в поле базы данных. Код выглядит так:
$serializedDataObject = base64_encode(serialize($objectInstance->myDataObject));
Когда я хочу оживить этот объект и вернуть его, я просто запускаю обратное
$unserializedDatanObject = unserialize(base64_decode($serializedDataObject));
Пока это работает хорошо. Но иногда мой php-скрипт терпит неудачу. Я думаю, что он не работает на этапе сериализации. Мой вопрос теоретически говорит о том, что может привести к сбою процесса сериализации и кодирования php? Существуют ли в массиве объектов данных определенные символы или виды данных, которые могут привести к сериализации?
Нужно ли мне массировать объект данных, прежде чем пытаться его сериализовать?
Редактировать:
Чтобы прояснить этот процесс,
У меня есть клиентское приложение Flex / Actionscript, которое отправляет объекты ActionScript на основе AMF на сервер. На стороне PHP я использую библиотеку Zend AMF для чтения данных AMF. Объект может быть проверен в PHP и в основном выглядит как ассоциативный многомерный массив. Именно в этот момент я пытаюсь выполнить сериализацию и базовую кодировку 64-го объекта, чтобы я мог сохранить объект в базе данных в виде закодированной строки.
Надеюсь, это имеет смысл. Проблема прерывистая и не так легко воспроизводить последовательно. Если я могу получить некоторые сообщения об ошибках, я отправлю их здесь для дальнейшего уточнения. Но на данный момент мне просто интересно, каковы пределы сериализации, которые помогут мне отлаживать дальнейшие действия.
Ресурсы не могут быть сериализованы, что может быть проблемой. Способ избежать этой проблемы – использовать магические методы: __sleep
и __wakeup
.
В принципе, ваша функция __sleep
вызывается, когда вы вызываете сериализацию, а __wakeup
– когда вы несериализуете, так что говорите, что это соединение с базой данных: во сне () закройте соединение и где-нибудь (возможно, сохраните строку соединения), и в режиме пробуждения снова подключитесь.
@Greg правилен тем, что вы не можете сериализовать ресурсы.
Учитывая, что вы описываете свои объекты как «объекты данных», я чувствую, что они содержат ваши ресурсы для подключения к базе данных? (например, $object->rs = mysql_connect(...);
).
Если да , рассмотрите возможность использования __sleep()
и __wakeup()
в ваших объектах данных ( __sleep()
вызывается непосредственно перед сериализацией __wakeup()
сразу после де-сериализации).
Функция __sleep()
должна закрывать любые базы данных или файловые ресурсы, а __wakeup()
должна повторно подключаться к базе данных.
В приведенной выше ссылке руководства PHP, приведенной выше, приведен пример класса, который управляет соединением DB, которое сериализуется:
<?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(); } }
Вы не можете правильно сериализовать ресурсы, такие как дескрипторы файлов или подключения к базе данных. Вы также не можете сериализовать встроенные объекты PHP, хотя я не совсем уверен, что это покрывает.
На php.net/bas64_decode есть некоторые упоминания о больших строках, не хорошо декодирующих. Кроме того, если у вас есть неподдерживаемые форматы символов в объекте, это может вызвать проблемы.
Надо идти с Томом на этом; процитировать php.net/serialize :
Значение для сериализации. serialize () обрабатывает все типы, кроме типа ресурса. Вы можете даже сериализовать () массивы, содержащие ссылки на себя. Также будут сохранены циклические ссылки внутри массива / объекта, который вы сериализуете. Любая другая ссылка будет потеряна.
Что касается стандартных объектов, у вас не должно быть проблем. Зарегистрируйте данные, которые вы получаете после base64_encoding / decoding, затем используйте следующую строку, чтобы проверить свои данные.
echo '<pre>'; print_r($decodedObject); echo '</pre>';
Вы храните сериализованные данные внутри базы данных? Если да, то является ли поле достаточно большим для хранения данных? Кодировка Base64 добавляет примерно в 1,3 раза к длине строки, которая будет усечена в некоторых системах БД.