I'm having a few issues with foreach loops in PHP.
I have an outer foreach loop and an inner foreach loop.
The basics of the loops are, I have some posted data from a form, and some data from a db. The outer loop, loops through each post data and then compares this with data from the database inner loop.
The issue I have is, upon each outer loop, if an entry is found on the inner loop, how does the outer loop know its been found and then not repeat the entry.
So, here's the code I am using, i've commented so you can see the problem im having with the logic
// get posted data
foreach($posted_vals as $post_key => $post_value) {
// query all data in assignments table
foreach($existing_ids as $db_key => $db_value) {
// check if user_id($db_value) matches ($post_value),
// if not then post to db
// if this loop does not find matching data and
// posts to the database, how does the outer loop
// know its been found and then not post again to database
}
// any entries not found in db, post to db ... er but hang on,
// how do i know if any entries were posted???
}
you can set a flag variable isFound whether the post were found in inner loop or not. Initially the variable is false but if the post is found in inner loop it will be updated to true then in outer loop you can check if the isFound is true or fale. Thus you can check whether your post was found or not in inner loop. Here is how you can do it:
// get posted data
foreach($posted_vals as $post_key => $post_value) {
$isFound = false;
// query all data in assignments table
foreach($existing_ids as $db_key => $db_value) {
//if found in db then set $isFound = true;
}
//if(!isFound) that means if the post was not found
// any entries not found in db, post to db ... er but hang on,
// how do i know if any entries were posted???
}
It might become more clear when you put the db-comparison in a separate function:
foreach($posted_vals as $post_key => $post_value) {
if(compareWithDbValues($post_value)) {
return true;
}
}
function compareWithDbValues($post_value) {
foreach($existing_ids as $db_key => $db_value) {
if($db_value == §post_value) {
return true;
}
}
return false;
}
If you do not have it in a separate function just use break instead of return true in the inner for loop.
Related
I've seen a few questions and the ones worth referencing
How can i delete object from json file with PHP based on ID
How do you remove an array element in a foreach loop?
How to delete object from array inside foreach loop?
Unset not working in multiple foreach statements (PHP)
The last two from the list are closer to what I'm intending to do.
I've got a variable names $rooms which is storing data that comes from a particular API using Guzzle
$rooms = Http::post(...);
If I do
$rooms = json_decode($rooms);
this is what I get
If I do
$rooms = json_decode($rooms, true);
this is what I get
Now sometimes the group exists in the same level as objectId, visibleOn, ... and it can assume different values
So, what I intend to do is delete from $rooms when
group isn't set (so that specific value, for example, would have to be deleted)
group doesn't have the value bananas.
Inspired in the last two questions from the initial list
foreach($rooms as $k1 => $room_list) {
foreach($room_list as $k2 => $room){
if(isset($room['group'])){
if($room['group'] != "bananas"){
unset($rooms[$k1][$k2]);
}
} else {
unset($rooms[$k1][$k2]);
}
}
}
Note that $room['group'] needs to be changed to $room->group depending on if we're passing true in the json_decode() or not.
This is the ouput I get if I dd($rooms); after that previous block of code
Instead, I'd like to have the same result that I've shown previously in $rooms = json_decode($rooms);, except that instead of having the 100 records it'd give only the ones that match the two desired conditions.
If I am not totally wrong, then this should do the trick for you:
$rooms = json_decode($rooms);
$rooms->results = array_values(array_filter($rooms->results, function($room) {
return property_exists($room, 'group') && $room->group != "banana";
}));
Here is a verbose and commented version of this one above:
$rooms = json_decode($rooms);
// first lets filter our set of data
$filteredRooms = array_filter($rooms->results, function($room) {
// add your criteria for a valid room entry
return
property_exists($room, 'group') // the property group exists
&& $room->group == "banana"; // and its 'banana'
});
// If you want to keep the index of the entry just remove the next line
$filteredRooms = array_values($filteredRooms);
// overwrite the original results with the filtered set
$rooms->results = $filteredRooms;
I'm working with data from Formstack's REST API. Everything is in XML format. I wrote some PHP to process it, and for some reason when I echo $valueVar in a foreach loop only the value from the first entry is returning for each of the three entries. I really don't know why the string isn't getting replaced. Could someone please shed some light on what I'm doing wrong.
Thank you!
PHP Output
Formstack API XML Output
foreach($xml->submissions->submission as $submission) {
foreach($xml->submissions->submission->data->XML_Serializer_Tag as $serializer) {
$fieldeVar = (string)$serializer->field;
$valueVar = (string)$serializer->value;
if ($fieldeVar=="95733876") {
echo $valueVar;
break;
}
}
}
I think this is a simple case of your 2 loops clobbering each other. Notice how you're defining the inner loop as foreach($xml->submissions->submission->.... That will always grab the first instance. It should be using $submission which your outer loop is setting up for you.
Just change
foreach($xml->submissions->submission as $submission) {
foreach($xml->submissions->submission->data->XML_Serializer_Tag as $serializer) {
to this
foreach ($xml->submissions->submission as $submission) {
foreach ($submission->data->XML_Serializer_Tag as $serializer) {
Output
prefix = Dr first = Argnes last = Acmefirst = Bobby last =
Leamalotfirst = Tina last = Students
I made a post regarding a code for Adobe Analytics API. I am using a code to retrieve the first and second element (dimension) which is called 'breakdown'. The number varies depending on the data we have for this element.
I am using a loop with i=10 but I want to take everything. Which is the best way to achieve that?
I am using this code:
foreach ($json->report->data as $element)
{
// putting an excessive number for i
for ($i=0;$i<100;$i++)
{
// checking if the object exists
if (isset($element->breakdown[0]->breakdown[$i]->name))
{
echo $element->breakdown[0]->breakdown[$i]->name;
// putting the data in a list I created before
array_push($list, array(''.$element->year.'-'.$element->month.'-'.$element->day, $element->breakdown[0]->name, $element->breakdown[0]->breakdown[$i]->name, $element->breakdown[0]->breakdown[$i]->counts[0], $element->breakdown[0]->breakdown[$i]->counts[1]));
}
else
{
// Break the loop. All the objects are in the row. So, if there is not any for i=45 then there won't be any for i>45
continue;
}
}
}
where I am trying to get all the objects. I am checking if the objects exist. If they don't, I want this loop to stop (second loop).
Use break instead of continue to exit a loop
break stops the current loop continue goes to the next iteration of the loop.
To get out of both loops use break 2;
You can break the loop with break.
for more information: http://php.net/manual/en/control-structures.break.php
foreach ($json->report->data as $element)
{
// putting an excessive number for i
for ($i=0;$i<100;$i++)
{
// checking if the object exists
if (isset($element->breakdown[0]->breakdown[$i]->name))
{
echo $element->breakdown[0]->breakdown[$i]->name;
// putting the data in a list I created before
array_push($list, array(''.$element->year.'-'.$element->month.'-'.$element->day, $element->breakdown[0]->name, $element->breakdown[0]->breakdown[$i]->name, $element->breakdown[0]->breakdown[$i]->counts[0], $element->breakdown[0]->breakdown[$i]->counts[1]));
}
else
{
// Break the loop.
break;
}
}
}
I have a class that does the MySQL stuff for me.
I have 1 to n rows in a MySQL Table and want to query specific results.
To query a table, I can now use
$db->select('tablename', '*');
$res = $db->Result()
to get the results as an associative array.
Now if I want to loop through, I have to check if there is one or more results and then either display that one result or loop through the results.
This bloats up my code and I would like to find a way to combine both results.
At the moment, I am doing this stuff like so:
if(is_array($res[0]){
//we have more than one result
foreach($res as $something)
{
//do stuff here
}
}
else
{
//do the same stuff as above here but now with other variables since $something is only filled in the foreach loop
}
Now as said, I would love to combine those two and have only one piece of code to display the results (or work further with them)
Change the input data structure into the format the loop expects, then iterate through it in the loop:
if(!is_array($res[0]){
$res[0] = [$res[0]];
}
foreach($res as $something)
{
//do stuff here
}
I would suggest you to switch to some wide deveoped classes like PDO (http://php.net/manual/en/book.pdo.php) or simply add a check in your Result method that returns an empty array in cases there are no results
function Result() {
// stuff to fetch and fill $arr;
return (is_array($arr[0])) $arr : array();
}
Im trying to NOT show a specific field inside the loop, so I need to get a list of all the field types so I can use it inside the if statement. Not sure how I can do this properly?
foreach($this->sections as $k => $section){
foreach($section['fields'] as $k => $type){
//This makes a nice list of all the stuff I need
echo '<li>'.var_dump ($type['type']).'</li>';
}
//Outside the loop doesn't dump all of the contents just some
echo '<li>'.var_dump ($type['type']).'</li>';
if($type['type'] != 'switch'){
//My stuff
}
}
The idea is to loop all the field types, except for one specific type declared in the if statement. The for each is so I can get a list of all the field types.
As you might already experienced the construct you propose is not desired since the if statement will be executed after the loop has already ended.
You can use the continue keyword to jump to the next iteration and skip fields you're not interested in.
foreach ($section['fields'] as $k => $type) {
if ($type['type'] != 'switch') {
continue;
}
// do stuff
}
http://php.net/manual/en/control-structures.continue.php