PHP : Function Reference : WDDX Functions : wddx_deserialize
medvitz
You can also serialize instantiated class objects with the wddx functions.
ie.
$packet_id = wddx_packet_start("PHP");
wddx_add_vars($packet_id, "objvar");
$packet = wddx_packet_end($packet_id);
$a = wddx_deserialize($packet);
$obj = $a[objvar];
now $obj is a useable object, that looks like the original.
Note that with this method, you need to know what the variable name of the original object was. You can use one of the array functions to get the object in the event that the original object's variable name was unknown.
*** only verified on linux with 4.0.2
mail_fidel
To properly deserialize a wddx file it was to be utf8_encoded.
The following code will NOT work (PHP5.0.2 FreeBSD):
<?php
$data = wddx_serialize_value(array("xyzåäö","abcd"));
print $data;
print_r(wddx_deserialize($data));
?>
Even thought the serialization is done right, the deserialization will not work unless you encode the text using utf8.
This code WILL work:
<?php
$data = wddx_serialize_value(array(utf8_encode("xyzåäö"),"abcd"));
print $data;
print_r(wddx_deserialize($data));
?>
djm
The packet string you pass to this function doesn't have to be sanitized first; it searches for a WDDX packet within the string. So the string can contain HTML markup and random text outside of the packet, and that is all ignored.
This means you can get a packet from another web page like this:
$fhandle = fopen("http://myserver.com/packet.php", "r");
if ($fhandle) {
$page = fread($fhandle,10000);
fclose($fhandle);
$value = wddx_deserialize($page);
print "pi is: " . $value["pi"] . "
\n";
} else {
print "could not get packet.php
";
}
php dot net
On migrating wddx_deserialize() from PHP 4.x to PHP 5.1 (5.1.0RC6):
While
$buffer = wddx_serialize_vars($some_array);
$some_array = wddx_deserialize($buffer);
worked fine with PHP 4.x, the deserialization failed with PHP 5.1. In the above example $some_array will just be an empty string under 5.1
While wddx_serialize_vars() seems to behave identical in 4.x and 5.1, wddx_deserialize() does NOT.
Prepending XML encoding information to the buffer turned out to be at least a workaround. So, the following works with PHP 5.1:
$buffer = wddx_serialize_vars($some_array);
$buffer = '<?xml version="1.0"
encoding="ISO-8859-1"?>'.
$buffer;
$some_array = wddx_deserialize($buffer);
NB: It may well be, that the behavioural difference between 4.x and 5.1 described above can only be observed if the array contains certain characters, i.e. german Umlaute (äöüÄÖÜ). So this workaround may not be necessary in each and every case.
xavier
JavaScript/PHP interroperability:
If you want to exchange wddx packets between a JavaScript application using the JS wddx library from openwddx (http://www.openwddx.org/downloads/), and a PHP script using wddx functions, be aware that the encoding of the classes of objects serialized in the wddx packet is not made the same way in both implementations.
The JS lib uses a 'type' attribute in the 'struct' tab and gives it the name of the class of the object serialized in the 'struct' element, while PHP uses a 'php_class_name' tag within the 'struct'.
NB : to get the type attribute with JS serialisation, you need to set the 'wddxSerializationType' member in your classes
Example with an object of class 'exemple' containing 2 members _attr1 and _attr2.
(NB : in french, 'example' is spelled 'exemple', okay ? :-)
JS serialization :
<wddxPacket version='1.0'>
<header/>
<data>
<struct type="exemple">
<var name='_attr1'>
<string>foo</string>
</var>
<var name='_attr2'>
<string>bar</string>
</var>
</struct>
</data>
</wddxPacket>
php serialization:
<wddxPacket version='1.0'>
<header/>
<data>
<struct>
<var name='php_class_name'>
<string>exemple</string>
</var>
<var name='_attr1'>
<string>foo</string>
</var>
<var name='_attr2'>
<string>bar</string>
</var>
</struct>
</data>
</wddxPacket>
I like the JS approach better.
So if you need the compatibility, the workaround is quite simple:
- add a 'php_class_name' member in your JS objects, giving it the name of the class for value, and the JS generated packet will be correctly deserialized with PHP in classed objects.
- use a regexp on a PHP generated packet to add the 'type' attribute so that the JS deserialization instanciates objects of the right class:
$pat = "/<struct><var name='php_class_name'><string>(\w+)<\/string>/" ;
$rep = "<struct type='\$1'><var name='php_class_name'><string>\$1</string>" ;
$serialised = preg_replace($pat, $rep, $serialised );
NB : this only works because the 'php_class_name' tag is just next to the 'struct' tag.
Who knows if this is going to be true in future releases... ?
This way, you can exchange JS and PHP objects (provided you define your JS and PHP classes the same way) smoothly...
It's worth saying that both implementations, as well as my interroperability workaround, handle correctly objects with members that are also objects.
NB : NB means Nota Bene.
php
if you have WDDX data coming from a third party source and it isnt being parsed correctly in your php, try translating their WDDX. we have a third party sending us WDDX from cold fusion, and it uses a <recordset> element, which PHP seems to ignore (looking around the web we found some other people having trouble) so the (hopefully temporary) solution we found was to translate the WDDX midstream and then we were able to parse it:
$url = "http://somedomain.com/blah.wddx";
$fp = fopen($url,"r");
$page = fread($fp,10000);
fclose($fp);
$page = str_replace("<recordset","<struct",$page);
$page = str_replace("</recordset","</struct",$page);
$page = str_replace("<field","<var",$page);
$page = str_replace("</field","</var",$page);
$values = wddx_deserialize($page);
while(list($key,$val) = each($values)) {
print "$key => $val ";
}
this works for us. it's a hack, and hopefully php will support this in the future or something.
dave
Here's a handy wddx_deserialize clone I wrote a while back. It uses PHP5 SimpleXML and recursion to do pretty much the same task as wddx_deserialize. Hope it comes in handy for someone.
<?php
if (!function_exists('wddx_deserialize'))
{
/**
* Clone implementation of wddx_deserialize
*/
function wddx_deserialize($xmlpacket)
{
if ($xmlpacket instanceof SimpleXMLElement)
{
if (!empty($xmlpacket->struct))
{
$struct = array();
foreach ($xmlpacket->xpath("struct/var") as $var)
{
if (!empty($var["name"]))
{
$key = (string) $var["name"];
$struct[$key] = wddx_deserialize($var);
}
}
return $struct;
}
else if (!empty($xmlpacket->array))
{
$array = array();
foreach ($xmlpacket->xpath("array/*") as $var)
{
array_push($array, wddx_deserialize($var));
}
return $array;
}
else if (!empty($xmlpacket->string))
{
return (string) $xmlpacket->string;
}
else if (!empty($xmlpacket->number))
{
return (int) $xmlpacket->number;
}
else
{
if (is_numeric((string) $xmlpacket))
{
return (int) $xmlpacket;
}
else
{
return (string) $xmlpacket;
}
}
}
else
{
$sxe = simplexml_load_string($xmlpacket);
$datanode = $sxe->xpath("/wddxPacket[@version='1.0']/data");
return wddx_deserialize($datanode[0]);
}
}
}
?>
xavier
Beware, although the deserialized objects are instanciated class objects (if the php_class_name tag is amongst the children of the struct tag and its text content is the name of a loaded class), the constructor of the class has not been called at all.
You can use the members and call the methods of the object all right, but any initialisation action that the constructor might be in charge of is missing.
djm
At least in PHP 4.0B2, this function kills your PHP script if you feed it something that doesn't contain a well-formed WDDX packet. For example, this program:
<pre>
$value = wddx_deserialize("foo");
</pre>
doesn't return an error code, but instead you get
this back from apache:
<pre>
<HTML>
<HEAD>
<TITLE>
An Error Occurred
</TITLE>
</HEAD>
<BODY>
<H1>An Error Occurred</h1>
500 - Unexpected EOF.
</BODY>
</HTML>
</pre>
This happens even if you prefix the command with @,
which turns off error reporting.
|
|