views:

927

answers:

3

A function in my application does the following:

  • Capture Web Page using Snoopy
  • Load result into DOMDocument
  • Load DOMDocument into Simple XML Object
  • Run XPath to isolate section of document required
  • json_encode the result and save to database for later use.

My problem arises when recovering this block from the database, and decoding it. I can see the @attributes when I var_dump the object, but cannot find a combination of commands that allows me to access them.

Error message is: Fatal error: Cannot use object of type stdClass as array

Below is a sample of my object. I have tried, amongst other what used to work.

echo $obj['class'];

stdClass Object
(
    [@attributes] => stdClass Object
        (
            [class] => race_idx_hdr
        )

    [img] => stdClass Object
        (
            [@attributes] => stdClass Object
                (
                    [src] => /Images/Icons/i_blue_bullet.gif
                    [alt] => image
                    [title] => United Kingdom
                )

        )

    [a] => Fast Cards
)
A: 

If an object is converted to an array, the result is an array whose elements are the object's properties.

$asArray = (array)$myObj;
echo $asArray['@attribute'];
Lawrence Barsanti
this still does not work, probably due to what stefan said about @ being a reserved character.
esryl
That's because only the *exterior* stdClass is converted to an array, all of the array values would still be stdClass Objects. However if you used decode_json($json_string, TRUE) *note the true boolean*. Then you could access $array['@attribute']. --the '@' is a string at this point and not *reserved*.
null
+2  A: 

I actually don't really understand what you're trying to do and where the error is thrown, but to access the properties of your object you can use

echo $obj->{'@attributes'}->class; // prints "race_idx_hdr"
echo $obj->img->{'@attributes'}->src; // prints "/Images/Icons/i_blue_bullet.gif"
echo $obj->img->{'@attributes'}->alt; // prints "image"
echo $obj->img->{'@attributes'}->title; // prints "United Kingdom"
echo $obj->a; // prints "Fast Cards"

This weird syntax ($obj->{'@attributes'}) is required because the @-symbol is reserved in PHP and cannot be used for identifiers.

Stefan Gehrig
{@stefan} - you legend ;). well that my new fact of the day, @ is a reserved symbol.
esryl
update: json_encoding simplexml seems to drop a ton of information. so i am changing accepted answer to saving raw xml in the db instead.
esryl
+3  A: 

When you decode the json from the database, you get an object of type 'stdClass' instead of the original type 'SimpleXMLElement' returned by the SimpleXMLElement::xpath function.

The stdClass object does not 'know' about the pseudo array syntax used by SimpleXMLElement objects to allow accessing the attributes.

Normally you would use the serialize() and unserialize() functions instead of json_encode/decode to store objects in a database, but unfortunately, SimpleXMLElements are not working with those.

As an alternative, why not just store the actual xml and read it back to SimpleXML after fetching it from the database:

// convert SimpleXMLElement back to plain xml string
$xml = $simpleXML->asXML();

// ... code to store $xml in the database
// ... code to retrieve $xml from database

// recreate SimpleXMLELement
$simpleXML = simplexml_load_string($xml);
Henrik Opel
i like this as well. i might just do that :) thank you.
esryl
this is actually the only solution as json_encode loses a heap of data.
esryl