tags:

views:

169

answers:

4

While populating an array with data from a SimpleXML call, PHP throws exception to what it believes as 'Undefined' keys, however, the output is actually correct.

$doc = new SimpleXmlElement($http_result, LIBXML_NOCDATA);

$result = array();

$x = 0;

foreach($doc->users->user as $item) {
    $result['user'][$x]['id'] .= $item->id;
    $result['user'][$x]['name'] .= $item->name;
    $result['user'][$x]['email'] .= $item->email;
    $x++;
}

print json_encode($result);

This actually outputs what I expect, i.e. {"user":[{"id":"4843977","name":"Test New User","email":"[email protected]"}]}

However, the following errors are also present, and I'm not totally sure why - this doesn't appear in 5.2.6 but does for 5.2.10

Notice: Undefined index: user in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined offset: 0 in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined index: id in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined index: name in /var/vhosts/sys-dev/docs/file.php on line 37

Notice: Undefined index: email in /var/vhosts/sys-dev/docs/file.php on line 38

Notice: Undefined offset: 1 in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined index: id in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined index: name in /var/vhosts/sys-dev/docs/file.php on line 37

Notice: Undefined index: email in /var/vhosts/sys-dev/docs/file.php on line 38

Notice: Undefined offset: 2 in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined index: id in /var/vhosts/sys-dev/docs/file.php on line 36

Notice: Undefined index: name in /var/vhosts/sys-dev/docs/file.php on line 37

Notice: Undefined index: email in /var/vhosts/sys-dev/docs/file.php on line 38
+3  A: 

I think You must change just ".=" to "=" in lines:

$result['user'][$x]['id'] = $item->id;
$result['user'][$x]['name'] = $item->name;
$result['user'][$x]['email'] = $item->email;
Kamilos
That'll get rid of most of the errors, but won't get rid of `Notice: Undefined offset: 1 in /var/vhosts/sys-dev/docs/file.php on line 36`.
Dominic Rodger
Maybe try it in loop (without $X): $result['user'][] = array( 'id' => $item->id, 'name' => $item->name, 'email' => $item->email );
Kamilos
This ends up outputting `{"user":[{"id":{"0":"4843977"},"name":{"0":"Test New User"},"email":{"0":"[email protected]"}}]}` which is usable. Although I can see and understand why .= probably shouldn't be used, it was the only way I could get readable JSON output.
jakeisonline
".=" or "=" doesn't read the JSON output, it just assign value to the var on the left. Now You don't have yet $result['user'][$x]['id'] index then must create it with "=".
Kamilos
+3  A: 

You don't define what are $result['user'] and $result['user'][$x]. You need to instantiate them as array so you won't get that error.

$result['user'] = array();
foreach($doc->users->user as $item) {
    $result['user'][$x] = array();
    $x++;
}

For the undefined indexes in the fields, the problem is similar. You use ".=" when the variable doesn't exists yet. So you should instantiate it first with an empty string.

$result['user'][$x]['name'] = '';
Damien MATHIEU
The initialization of the arrays is not necessary. Even the multi-dimensional attributes are initialized the moment they are filled for the first time
Cassy
+1  A: 

You need to initialize the $result array first:

$result = array('user' => array());

And since you’re using the string concatenation and assignment operator .=, that would also apply to the $result['user'][$x] arrays:

foreach($doc->users->user as $item) {
    $result['user'][$x] = array(
        'id'    => null,
        'name'  => null,
        'email' => null
    );
    $result['user'][$x]['id'] .= $item->id;
    $result['user'][$x]['name'] .= $item->name;
    $result['user'][$x]['email'] .= $item->email;
    $x++;
}

But that’s not necessary since you can also write it like this:

$result = array('user' => array());
foreach($doc->users->user as $item) {
    $result['user'][] = array(
        'id'    => $item->id,
        'name'  => $item->name,
        'email' => $item->email
    );
}


Edit    Since we elaborated that the attributes of $item are SimpleXMLElement objects too, $item->attr[0] is required to address the string value itself. Thus:

$result = array('user' => array());
foreach($doc->users->user as $item) {
    $result['user'][] = array(
        'id'    => $item->id[0],
        'name'  => $item->name[0],
        'email' => $item->email[0]
    );
}
Gumbo
What’s wrong? Why did this answer got voted down?
Gumbo
Not sure why it was voted down. Anyway, this solution works, but yields the same results as all other answers so far: `{"user":[{"id":{"0":"4843977"},"name":{"0":"Test New User"},"email":{"0":"[email protected]"}}]}` which isn't really valid JSON output
jakeisonline
@jakeisonline: The item attributes like `$item->id` are probably not strings but some other objects instead. So try something like `$item->id[0]`.
Gumbo
@gumbo: you're right, it's adding them as an SimpleXMLElement Object. Referring to it using $item->id[0] seems to make no difference, as it still shows as `[id] => SimpleXMLElement Object ( [0] => 4802022 )` when your print_r the array, which means a further array is being added to the JSON output (or, indeed, any output)
jakeisonline
@gumbo: thanks for revising your answer, much appreciated. However, this still outputs odd data. For example: `Array ( [user] => Array ( [0] => Array ( [id] => SimpleXMLElement Object ( [0] => 4802022 ) [name] => SimpleXMLElement Object ( [0] => Dropbox Test User.....` I'm at a loss as to why it's dumping the object reference as opposed to just the string/value.
jakeisonline
@jakeisonline: Did you change the code replacing `$item->attr` with `$item->attr[0]`?
Gumbo
@gumbo: exactly as you have it in your editted snippet.
jakeisonline
@jakeisonline: And what does `var_dump($item->id[0])` print out?
Gumbo
It'll print out something like `object(SimpleXMLElement)#10 (1) { [0]=> string(7) "4802022" }`
jakeisonline
@jakeisonline: Are you really using `var_dump($item->id[0])` and not just `var_dump($item->id)`?
Gumbo
@gumbo: cross my heart and hope to die really!
jakeisonline
A: 

It happens, because you're not just setting the array values, but you're concatenating to the current value:

$result['user'][$x]['id'] .= $item->id;

This line means "take the current value of $result['user'][$x]['id'] and add $item->id to it". The notice is then thrown, because the current value is not yet existent.

Amend the code to this

$result['user'][$x]['id'] = $item->id;

and you should be safe. No idea though, why 5.2.6 is not throwing the errors, maybe you should check with the error_reporting setting in the php.ini.

Cassy