Array_push pushing empty values - php

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;

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

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);

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 )

Related

Overwrite the original array values in PHP in nested loop

Cutting out some of the code on the innermost foreach, I'm trying to change HERE to make it so that it alters the original value. I want to pass a pointer basically and alter it. I was able to kind of do this with the &$ keyword in the foreach but (as the docs state) it results in some buggy behavior and I'm trying to do it the way they, and others on SO suggest. The problem is all the examples I find are for a single foreach, not for nested.
The following code loops properly but when I get to the HERE it doesn't actually alter the original value. Also worth mentioning that $sources could be an array of arrays (by index) or an array of key values. This looping code seems to iterate over both fine though, just not overriding the original value of $sources
fwiw, on top of the &$ I also tried:
$sources[$sourceKey][$rowKey][$cellKey] = $date->format('m/d/Y');
Which $sources[$sourceKey][$rowKey][$cellKey] returns the right value if I print it but it still doesn't overwrite the original array.
function convertDates($sources) {
foreach($sources as $sourceKey => $sourceValue){
foreach ($sourceValue as $rowKey => $rowValue) {
foreach ($rowValue as $cellKey => $cellValue) {
HERE = $date->format('m/d/Y');
}
}
}
}
I never could get this to work correctly since there were two formats this loop could get (JSON encoded object and an array). Making it work for both was much harder than just doing it in JavaScript so instead of modifying on the server I format the data how I want client side and send it up. This formatting is purely presentational and for personal use so if someone were to put in a debugger and change the code to send a different format thats fine and there's no security issues.
So in the end, this code was rewritten in JS and since JS handles arrays and objects using the same pointers the above issue wasn't an issue any longer.

Sorting a big JSON object with a smaller JSON object in PHP

Before the cries of "DUPLICATE" begin, I've used several posts here and elsewhere as guides in trying to solve this problem and they've taken me a long way, but I'm stuck at the last step.
I have a JSON object that goes five deep. This object is used to populate a table on a webpage. Each item in the table has a score from 0-100, but they just get tossed into the table haphazardly. I want them to appear sorted with the lowest scores at the top.
What I did:
$jarr = json_decode($json, true);
$marr = $jarr['g'];
foreach ($marr as $key => $row){
$score[$key] = $row['score'];
$component[$key] = $row[$key];
}
array_multisort($score, SORT_ASC, $component, SORT_STRING, $marr);
print_r($marr);
Reasoning: the smaller object 'g' is an array of associative arrays inside the larger JSON object and is the only one that actually needs to be sorted, so I operated on only that portion and got functional code.
When I put this snippet into the source, it didn't break the page but I'm only getting the output of the scores; I need all the other information inside the lower arrays, also. I tried applying the logic to the larger JSON object, but that did nothing (could just be user error, here), and I tried sorting the smaller object and printing the larger one.
How can I return the whole JSON object with the 'g' object sorted?
Edit: I've found that part of the problem is that the source code isn't turning the JSON into an array where my code snippet is. That explains why they're not compatible, but still leaves me trying to get the sorting working.
That code does what I need it to. The last step was just to cast the resulting array as an object and make sure the Smarty code was referencing everything correctly.

associative array overwriting entries php

I am trying to build an associative array to save the following information. A url, a word, and a frequency (# of occurrences of that word on that webpage).
I want to be able to access the information where I enter a string for the url and word and receive the frequency, like this:
$test["somewhere.com"]["biology"] => 5
$test["somewhere.com"]["auto"] => 10
$test["elsewhere.com"]["biology"] => 7
Right now I am pulling the information out of a db one row at a time and am trying the following:
$test["$url"] = array("$word" => "$freq");
After every iteration it gets over written. How do I change the syntax to avoid this situation? Is it possible to build the structure I want?
Thanks.
EDIT:
I was assigning values to array in a while loop. I made the mistake of initializing the array within the loop. I wasn't overwriting entries, I was
re-initializing the array unintentionally. That was my problem.
You are reassigning $test["$url"] as a new array each time. Use the full path:
$test[$url][$word] = $freq;
Also, no need for the quotes.
Instead of overwriting the first level contents, declare a new property for it. (without knowing how are you getting your urls, words and frequencies, the following is just an example)
$test = []
foreach($urls as $url => $words) {
$test[$url]=[];
foreach( $words as $word => $freq) {
$test[$url][$word] = $freq;
}
}
However, this looks awfully like trying to build an associative array that's already built.

PHP referencing variables in an array as foreach keys

I know my title is quite ambivalent but if you bear me, you'll find it is not so bad :P
I have a class method that gets quite different database fields in any order and builds an array based on those fields (each key adds another level into the array).
Now, that's the easy part. I also have a correction function that unifies the e.g. costs by some demographic data. The problem is that I need to address the right level in the correction formula.
I try to make an example:
I ask fields A,year,B,C,D and my correction formula for D depends on the year and C. I have formalized so that C and D are always the last ones to list but the problem is that how do I address the year so that I could get out an answer like [A][year][B]=function(year,c,d). The fields are in an array ($retr['fields']=array("A","year","B","C") (the result D comes automatically)
I tried to use foreach like
$retr['fields']=array("A","year","B","C")
$temp=get_data($retr);
foreach($temp as $${$retr['fields'][0]} => $yd)
foreach ($yd as $${$retr['fields'][1]} => $cd) {
$output[$${$retr['fields'][0]}][$${$retr['fields'][1]}]=0;
foreach ($cd as $a => $v)
$output[$${$retr['fields'][0]}][$${$retr['fields'][1]}]+=$v*$act[$year][$a]
and so on, but it seems that one can't use a variable variable as a key in foreach (or then I have got the syntax wrong). As now it just says that "Undefined variable: year"
Do you have any ideas how to express what I need?
Well I solved it, or rather not solved but programmed around.
For each foreach I checked the corresponding field and if it was year, I made a variable with value of current foreach key and referenced it with $$variable.
Like this:
$temp=get_data($retr);
foreach($temp as $varA => $yd) {
if ($retr[0]=="year")
$year_var=varA;
.
.
.
$output[$varA][$varB]+=$v*$act[$$year_var][$a]
I still would have preferred a cleaner solution but given my timeframe (or rather the loss of it) this should suffice.
I'm still interested in the "perfect solution"(TM)
Thx anyway :)
It's kind of hard to understand your structure, but it appears you're fetching some data items and then categorize them into tree-like structure.
In this case, even though a particular attribute (e.g. year) appears on some upper level it's still, essentially, an attribute of the data item itself, so keep it as such: convert the "value" into a non-scalar (either object or hash). Then you would be able to work with those attributes without referencing outer loop values (and without resorting to variable variables):
foreach($arr as $subarr) {
foreach ($subarr as $subsubarr) {
// ... and so on
foreach ($lastlevel as $value) {
$adjusted = correctionFunc($value->data, $value->year, $value->somethingelse); // assuming value is an object
}
}
}

Remove an item from an array?

I've created an array from a PHP session variable, and now I'm trying to use ajax (within jQuery) to remove an element from the array.
I've got the following code so far:
$val = $_SESSION['enquiry-basket'];
$array = explode($val);
foreach ($enquiries as $a => $q) {
if ($q == $_POST['product_id']) {
unset($array[$a]);
}
}
The only problem is, it doesn't remove the item.
Can anyone explain why, and tell me how to fix it?
Edit
Sorry guys. The reason I mentioned jQuery is because I use a jQuery ajax call to process the PHP I displayed above.
The ajax query runs fine because it processes some javascript goodies (remove's a div from the HTML) once the ajax returns a success.I've added the delimiter (can't believe I missed it) but the element doesn't get removed from the array still.
I've never been good at multi-dimensional arrays, so here's the array printed:
Array ( [0] => 6 [1] => 8 )
It looks right to me, but I'm an amateur in arrays. (6 and 8 are of course my strings I inserted)
explode is missing the first argument:
explode(',', $val);
You are removing item from $array, not from $_SESSION['enquiry-basket'].
The explode function should have two parameters. But you given only the name of the array.
explode(separator,string,limit);
If I understand correctly what you are trying to do, the problem is that JQuery runs client side, which means that your PHP arrays on the server side disappear between each request from Ajax. The only array that remains is $_SESSION.
If you want to use AJAX, you need to remove from $_SESSION directly. Anything else is just useless because the arrays and variables "disappear" between each call.
Mostly an issue with the explode function, the second parameter is missing:
Change from:
$array = explode($val);
To:
$array = explode('~',$val); // ~ is a delimiter

Categories