Search code examples
phparraysarray-push

Array_push pushing empty values


I'm trying to push data to an array inside a foreach loop. Empty values get pushed into the array.

I tried logging out the values to see if they were empty but they were there, they only go missing when pushing to the array. I also tried to just assign the value to another variable and that worked fine.

$winners = \App\Winner::where('gameid', 577)->pluck('prizes_web_1');
$xml = simplexml_load_string(stripslashes($winners));
$winners_1 = [];
foreach($xml->Winner as $v) {
   $out->writeln($v); //when logging here every value gets logged correctly
   array_push($winners_1, $v);
}
$out->writeln($winners_1); //here an array with 4 empty values gets logged

I tried declaring the array as array(), the issue stayed. Tried assigning the value like so winners_1[] = $v still everything remained the same. Also tried using strval($v) but that didn't help either

I can't figure out what is causing the problem, never have I come across something like that when pushing to arrays.

EDIT Here's an example of xml:

<?xml version='1.0' encoding='UTF-8'?>
<Winners>
    <Winner><name>Robb Stark</name></Winner>
    <Winner><name>Jon Snow</name></Winner>
    <Winner><name>Aria Stark</name></Winner>
    <Winner><name>Theon Greyjoy</name></Winner>
</Winners>

Also the $log->writeln() line are logging things to the console, when loging the $v I can see the values Robb Stark, Jon Snow etc logged, they dissapear when pushing to the array.

EDIT 2 Added more context to the sample code above.

EDIT 3 SOLUTION

Thank you @misorude

I just needed to cast my xml name element and it worked. $winners_1[] = (string)$v->name;


Solution

  • The issue here wasn’t really adding the elements into the array, but what was actually added - and how it got processed / interpreted later on.

    SimpleXML is what you’d traditionally call a “fickle mistress”. Often SimpleXMLElement instances behave like strings in certain contexts - but then don’t in a slightly different one.

    I didn’t go look up the inner workings of Symfony’s ConsoleOutput, but how exactly that creates output from the input objects has probably played a role here.

    Casper’s advice to cast them into strings was a good idea - if you don’t need any properties / methods a SimpleXMLElement object offers later on any more, and you just need their contained “data” - then casting them as soon as possible is a good way to avoid further troubles.

    You can not directly cast $v into a string here though - because the Winner element did not contain the text directly, but it was wrapped in an additional name element. Casting a SimpleXMLElement that in turn contains other elements into a string would just result in an empty string again.

    So the name element itself needs to be accessed and cast into a string here - (string) $v->name