Thursday, May 1, 2008

Interesting tidbit about PHP objects

I'm doing some XML stuff right now, using SimpleXML in PHP. One of the element groups I need to create is a list of descriptions in different languages. My original attempt looked like this:

$descriptions = array(
'en' => 'An awsome app.',
'es' => 'Una aplicacion chevere.',
'he' => 'אפליקציה מעולה',
);

foreach($descriptions as $loc => $desc) {
$d->addChild('description', $desc);
$d->description->addAttribute('locale', $loc);
}
echo $xml_post->asXML();


But that gave me an error:
Warning: SimpleXMLElement::addAttribute() [function.SimpleXMLElement-addAttribute]: Attribute already exists in...


When I looked at the code, the attribute was only getting plunked into the first <description> tag. The PHP engine thought that each time I went through the loop I was talking about the same $d->description when I asked it to stick a locale attribute in there. Weird. I expected the object to be treated like any other variable and get treated as a fresh thing. Nope.

If you put

echo $d->description . "<br />"

after the addChild() above, you'll see that it echoes out

an awesome app.
an awesome app.


If, however you change that block of code to

foreach($descriptions as $loc => $desc) {
$tag = $d->addChild('description', $desc);
echo $tag . "<br />";
}

you'll see that $tag prints out the correct description line for that pass through the loop:

An awsome app.
Una aplicacion chevere.
אפליקציה מעולה


So, the correct code to create the XML I want is

$descriptions = array(
'en' => 'An awsome app.',
'es' => 'Una aplicacion chevere.',
'he' => 'אפליקציה מעולה',
);
foreach($descriptions as $loc => $desc) {
$tag = $d->addChild('description', $desc);
$tag->addAttribute('locale', $loc);
}
echo $xml_post->asXML();


And then the XML comes out right.

<description locale="en">An awsome app.</description>
<description locale="es">Una aplicacion chevere.</description>
<description locale="he">אפליקציהמעולה</description>

No comments: