-2

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;

ReynaMoon
  • 171
  • 1
  • 12
  • 3
    Please provide xml sample. – u_mulder Aug 30 '19 at 09:23
  • And a sample of what your code does with that XML and also a description and example of what you actually want the code to produce as a result – RiggsFolly Aug 30 '19 at 09:27
  • It's hard to tell what `$out->writeln` stands for. You should probably use `var_dump` for debugging purposes and examine the output and update the question. – Dinu Aug 30 '19 at 09:27
  • did you try the "old school" method ? `$winners_1[] = $v` – pietro Aug 30 '19 at 09:27
  • Push if variable is not empty if(!empty($v)) – Casper Aug 30 '19 at 09:30
  • @Dinu `$out->writeln` is just logging values to the console – ReynaMoon Aug 30 '19 at 09:30
  • @pietro I did try that, the result is the same – ReynaMoon Aug 30 '19 at 09:31
  • @Casper The variable is not empty, when logging them to the console I can see the values, they only dissapear when pushing to the array – ReynaMoon Aug 30 '19 at 09:32
  • 1
    ___Sanity Check___ There is no reason to believe that `array_push()` is just picking on you. However there is more reason to suppose that an unknown function like `$out->writeln()` may be messing with the data it is asked to output. Please replace those with something you/we can trust like `var_dump()` – RiggsFolly Aug 30 '19 at 09:36
  • @Casper - using `empty()` in this situation might not be the best (it depends on what the OP want's, of course). That function considers values like: `0` and `0.0` (and more) to be empty but might very well be proper values you want. `empty()` is a function that could cause a lot of issues if you're not careful and understand how it actually works. – M. Eriksson Aug 30 '19 at 09:37
  • Try to cast XML element to a string before push $winners_1[] = (string) $v; – Casper Aug 30 '19 at 09:38
  • @RiggsFolly It was behaving the exact same way even before I added the `$out->writeln()` code, that was the only reason I added those lines to check if my `$v` had the values in the first place. The `$out` references to this Symfony component: `$out = new \Symfony\Component\Console\Output\ConsoleOutput();` – ReynaMoon Aug 30 '19 at 09:39
  • Please edit the code that actually reads and parses the XML data as well so we can get a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). It's easier for us to see what happens, and suggest solutions, if we can test the code ourselves. – M. Eriksson Aug 30 '19 at 09:41
  • _“Here's an example of xml:”_ - and you are parsing that how? Just SimpleXML? If so, and if your `$out->writeln` gets replaced by a simple var_dump, it shows this is working fine: https://3v4l.org/QgVTQ It might however be that the fact that the items are SimpleXMLElement instances creates the problem, if Symfonys ConsoleOutput component can’t handle those correctly. – misorude Aug 30 '19 at 09:43
  • @misorude I tried casting it to string like so: `$winners_1[] = (string)$v;` but the problem is still there. – ReynaMoon Aug 30 '19 at 09:45
  • @MagnusEriksson the xml string gets pulled from a db – ReynaMoon Aug 30 '19 at 09:46
  • 2
    Yes, just realized that. You are looping over the `Winner` elements here, but you have an additional `name` wrapped into those - so you can not cast the Winner SimpleXMLElement instance to string directly, but you need explicitly cast the name element instead: `(string) $v->name` – misorude Aug 30 '19 at 09:46
  • _"the xml string gets pulled from a db"_ - Ok. That's not what I asked about though :-) – M. Eriksson Aug 30 '19 at 09:46
  • @misorude Thank you, that fixed the problem, I will edit the post right away with your solution! – ReynaMoon Aug 30 '19 at 09:47
  • If the solution helped, then you shouldn't update your question with it. Either @misorude or you should write an answer that you can accept (following the SO format and marking the question as solved). – M. Eriksson Aug 30 '19 at 09:48
  • @MagnusEriksson Ah I see, I will do that right away! – ReynaMoon Aug 30 '19 at 09:52
  • @misorude can you write out your answer so I can mark it as solved? – ReynaMoon Aug 30 '19 at 09:53
  • Sure, no problem. – misorude Aug 30 '19 at 10:00

3 Answers3

1

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

misorude
  • 3,381
  • 2
  • 9
  • 16
0

Edit You only needed to define winners array like this $winners_1 = array(); not $winners_1 = [];//this is used in javascript i guess I'm new myself.

i tested this and it's working fine over here. try this,

$winners_1 = array();
foreach($xml->Winner as $v) {

  $out->writeln($v); //when logging here every value gets logged correctly
  $winners_1[] = $v;
}
$out->writeln($winners_1);
omi
  • 41
  • 4
  • 2
    `$winners_1[] = $v;` would be so much simpler, but either way would not stop the creation of occurances with blanks in – RiggsFolly Aug 30 '19 at 09:32
0

I think you are trying to add SimpleXMLElements elements to array. If you want to add the string value, you must cast the SimpleXMLElement to a string. Below I tried to reproduce your problem based on above discussion.

$myXMLData = "<?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>";

Based on PHP documentation xml to array https://www.php.net/manual/en/book.simplexml.php

$xml = simplexml_load_string($myXMLData);
$json = json_encode($xml);
$array = json_decode($json,TRUE);

Then loop,

$winners_1 = [];
foreach($array['Winner'] as $v) {
  array_push($winners_1, $v['name']);
}

print_r($winners_1);

Answer:

Array ( [0] => Robb Stark [1] => Jon Snow [2] => Aria Stark [3] => Theon Greyjoy )
Casper
  • 1,469
  • 10
  • 19