2009-08-27 2 views
2

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

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

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

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

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

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

Edit:

Чтобы уточнить процесс работает как этот

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

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

+1

Сбой вашего скрипта с определенными ошибками/исключениями? Поверните уровень ошибки вверх и убедитесь, что display_errors включен. – Ian

+0

Да, у меня есть отчет, но сообщения об ошибках для меня немного загадочны. Странно, что большую часть времени он работает. Объект данных не является слишком сложным, ints, string, booleans и date. Из того, что я могу сказать, он терпит неудачу из-за некоторой смены метки времени. Другими словами, когда объект сохраняется, кажется, является источником проблемы. –

+0

Возможно, мы сможем расшифровать сообщение об ошибке, если вы опубликуете его – Greg

ответ

3

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

+0

Он вызывает сериализацию() для объектов до кодировки их base64. Я уверен, что вы можете это сделать. Если я правильно помню, я думаю, что у меня есть производственный код, который делает это и правильно его обрабатывает. Но не тогда base64, кодирующий его. http://us.php.net/serialize –

+0

Вы можете сериализовать почти все, включая встроенные объекты PHP (они все еще являются объектами, предоставленными только ядром). Однако вы правы, вы НЕ МОЖЕТЕ сериализовать ресурсы. Поскольку OP ссылается на объекты данных, не сериализующиеся, у меня есть ощущение, что указанные объекты содержат ресурсы подключения к БД. – dcousineau

+0

Я помню, что не смог сериализовать RecursiveIteratorIterator, но, похоже, теперь исправлен - в моем простом тесте все равно – Greg

3

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

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

Должен пойти с Томом на этом; для обозначения php.net/serialize:

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

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

echo '<pre>'; print_r($decodedObject); echo '</pre>'; 
1

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

+0

, поле должно быть достаточно длинным. Я установил его longvarchar (в MySQL). Это там более длинный тип поля, который я должен использовать? Но по большей части работает мой скрипт. И большинство объектов примерно одного размера, поэтому я не думаю, что проблема заключается в сохранении базы данных. Я думаю, что это не может произойти после сериализации или кодирования. –

+0

Знаете ли вы, что данные вставляются в базу данных или происходит сбой в руке? Почему бы не попытаться написать простой итератор, который проходит через все записи, чтобы декодировать и не сериализовать данные и искать ошибку (base64_decode и un-serialize и возвращать false, если они не работают). Также я проверял ошибки для сериализации и un-serialize и обнаружил, что есть некоторые проблемы с certian builds и certian OS. Публикация той версии PHP и операционной системы, которую вы используете, может помочь определить, являются ли эти ошибки виновниками. – MANCHUCK

+0

Также попробуйте использовать текстовое поле для хранения данных. Это должно быть достаточно длинным для хранения данных. – MANCHUCK

4

@Greg правильный, поскольку вы не можете сериализовать ресурсы.

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

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

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

РНР ручной ввод Я связала выше есть пример класса, который управляет соединение с базой данных, которая serializeable:

<?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(); 
    } 
} 
5

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

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