Why It is not possible to serialize PHP built-in objects? - php

I have tried to unserialize a PHP Object.
Warning: unserialize() [function.unserialize]: Node no longer exists in /var/www/app.php on line 42
But why was that happen?
Even if I found a solution to unserialize simplexml objects, its good to know why php cant unserialize objects?
To serialize simplexml object i use this function
function serializeSimpleXML(SimpleXMLElement $xmlObj)
{
return serialize($xmlObj->asXML());
}
To unserialize an simplexml objetc i use this function
function unserializeSimpleXML($str)
{
return simplexml_load_string(unserialize($str));
}

SimpleXMLElement wraps a libxml resource type. Resources cannot be serialized. On the next invocation, the resource representing the libxml Node object doesn't exist, so unserialization fails. It may be a bug that you are allowed to serialize a SimpleXMLElement at all.
Your solution is the correct one, since text/xml is the correct serialization format for anything XML. However, since it is just a string, there isn't really any reason to serialize the XML string itself.
Note that this has nothing inherently to do with "built-in" PHP classes/objects, but is an implementation detail of SimpleXML (and I think DOM in PHP 5).

just inherent the class(the main xml class would be best) in a other one
and use __sleep
to store the data required to initialize simplexml(any object)
and __wake
to reinitialize the object as required
this way you can serialize(any object)
edit: remember this class needs to be accessible first,
this can be done by loading(including) the class or an __autoload

Related

PHP: array of objects - serialize vs json_encode - alternatives?

In PHP I'm having a real hard time using serialize/unserialize on a large array of objects (100000+ objects). These objects can be of a lot of different types, but are all descendants from a base class.
Somehow when I use unserialize on the array of objects about 0,001% of the objects are generated wrong! A whole different object is generated instead. This does not happen random, but each time with the same objects. But if I change the order of the array, it happens with different objects, so this looks like a bug to me.
I switched to json_encode/json_decode, but found that this always uses stdClass as the object's class. I solved this by including the classname of each object as a property, and then use this property to construct a the new object, but this solution is not very elegant.
Using var_export with eval works fine but is about 3 times slower than the other methods and uses much more memory.
Now my questions are :
what could cause the bug / wrong objects that are created with
unserialize ?
is there a better way to use json_decode with an array of objects, so that classes are somehow stored within the json
automatically?
is there maybe even an other method to read/write a large array of objects in PHP?
UPDATE
I'm beginning to believe there must be something strange with my array-data, because with msgpack_serialize (php extension, alternative to serialize) I get the same kind of errors (but strangely enough not the same objects are generated wrong!).
UPDATE 2
Found a solution : instead of doing serialize on the entire array, I do it on each object now, first serialize and then base64_encode and then I store each serialized object as a separate line in a text-file. This way I can generate the entire array of objects and then iterate each object using file() with unserialize and base64_decode : no more errors!
With serialize/unserialize functions 2 magic methods are connected.
__sleep()
serialize() checks if your class has a function with the magic name __sleep(). If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized. If the method doesn't return anything then NULL is serialized and E_NOTICE is issued.
With sleep you have better control on serializaction you can pass the variables that can be serialized and clean resources befere seralization.
When unserialize is called then the other function should be mentioned
__wakeup()
The intended use of __wakeup() is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.
About json_encode()
It doesn't have magic methods __wakeup, __sleep so you have less control
It doesn't serialize private properties
Objects are always stored as stdClass
Json_encode is faster than serialize
It's is up to you what you choose but for more advanced classes with db connection etc. I would suggest serialize()

From SimpleXMLElement to SimpleXMLIterator

I have a nice function that converts a (simple, duh) xml to an array, and to do so it uses the SimpleXmlIterator class.
It works quite well, but I'd like to make it accept not only xml source strings or SimpleXmlIterator objects, but SimpleXmlElements too since I use them way more often that iterators (that I use just in that function, actually).
What I did so far was
$iter = new SimpleXmlIterator($xml->asXML());
but to me it's like passing through Tokyo to get from Paris to London. After all, SimpleXmlIterator extends SimpleXmlElement, so is there a better way to convert a SimpleXmlElement object to a SimpleXmlIterator?
You can use SimpleXMLIterator at the beginning by setting the second parameter in http://php.net/manual/de/function.simplexml-load-file.php
$yourSimpleXMLIteratorObject = simplexml_load_file("your_file.xml","SimpleXMLIterator");
all Objects resulting, are now SimpleXMLIterator-Objects
Why not parse all your XML into SimpleXMLIterator objects to begin with if you plan to use them as such?
As far as I know there is not an easy way to convert/cast from SimpleXMLElement to SimpleXMLIterator. These classes simply wrap a libxml resource so you would think there would be a way to obtain a resource handle and pass it into SimpleXML* constructors, but if there is it's news to me.

PHP XML performance and serialize()

I have an XML file which contains the structure of some objects. The object is like this:
class Object:
{
private $name;
private $info;
private $$items;
}
Where $items is an array of objects, so it is recursive.
As of now, when I have to list the items I use simplexml to iterate within the elements and show them.
My questions are:
1) If I parse the XML and convert the data into the object instead of working with pure XML, would it affect the overall performance of the pages all that much? Will it slow down too much considering that every page the user loads he will have to load the items?
2) Is it a good idea to serialize() a recursive object like the one I’ve defined?
SimpleXML cannot be serialized because it's considered to be a resource. However, you can easily grab the output of $sx->toXML(); and serialize that, re-constructing the SimpleXMLElement(s) once you've unserialized them.
The performance difference of re-parsing the XML is not very considerable unless you're working with extremely large XML trees.
In regards to your object, you can also implement the __sleep() and __wakeup() magic methods that will allow you do alter the object before it is serialized and unserialized respectively.
When serializing your recursive object example, don't include your $$items variable in the __sleep() magic method and re-implement it in __wakeup.

Serialize a PHP object (Doctrine Query)

I'm trying to serialize a Doctrine_query object in Symfony :
var_dump(serialize($this->pager->getQuery()));
The result is :
string(2) "N;"
What am I doing wrong?
You can not serialize every object in PHP. Objects themselves - by implementing the Serializeable interface PHP Manual - can protect themselves from being serialized for example.
They return a NULL value then (or don't return anything which is then NULL in PHP). And that's exactly the contents of your serialized string: a serialized NULL (N;).
And there are even some build-in classes that go even further than that. But it applies as well to user-defined classes and build-in classes: Some of them are not available for serialization.
One example of a built-in class that can not be serialized in PHP is DOMDocument, however it is possible to add the functionality as the following question demonstrates:
How to serialize/save a DOMElement in $_SESSION?.

How-to Serialize/Unserialize a SimpleXML Object?

I've seen a few creative solutions for dealing with serialized SPL objects but am looking for more options (or elaborations). I store nested serialized objects - of which, one is SimpleXML - in the database, only to be un-serialized later. This obviously cause some problems.
$s = new SimpleXmlElement('<foo>bar</foo>');
$ss = serialize($s);
$su = unserialize($ss);
// Warning: unserialize() [function.unserialize]: Node no longer exists...
Does anyone have any insight into highly-reliable methods for dealing with serialized SPL objects? __sleep()/__wakeup() overrides? Cast-to-stdClass? Cast-to-string, then serialize?
Any help is appreciated.
[Edit: The scope and variation of these XML schemas are too varied to map with an ORM. They are, at their most fundamental level, arbitrary payloads in stateful processes, triggered within restful APIs.]
Questions on appropriateness notwithstanding, you can turn it back into XML like this:
$xml = $simpleXmlElem->asXML();
And then, when you pull it from the database:
$simpleXmlElem = simplexml_load_string($xml);
As for whether it's appropriate to just serialize large chunks of XML, it can be true that putting XML into the database removes much of the advantage of using a relational system, but you do have the advantage of being able to accommodate an arbitrary workload. If some fields are universal, and/or you gain benefit from normalizing them properly (e.g. you want to select based on those fields), move those into normalized columns.
More clear and OOP.
namespace MyApp;
class SimpleXMLElement extends \SimpleXMLElement
{
public function arrayToXml($array = array())
{
array_walk_recursive($array, array(&$this, 'addChildInverted'));
return $this;
}
public function addChildInverted($name ,$value)
{
parent::addChild($value,$name);
}
}
and calling
$xml = new \MyApp\SimpleXMLElement('<resultado/>');
echo $xml->arrayToXml($app->getReturnedValue())->asXML();
Wouldn't simply rendering and storing the XML be the best way to serialize any object that represents an XML structure?
What are you trying to do with the serialized data that might prevent this?
edit:
Also,
I store nested serialized objects [...] in the database, only to be un-serialized later
Why are you storing PHP serialized data in a database? There are many better ways to store objects in a database.

Categories