If Statement with Foreach not iterating through foreach - php

I am having an issue with my code - fairly new to PHP so any pointers would be appreciated.
I have the following code
foreach(findCustomAlerts($customerid) as $key=>$value){
echo "ID : ".$rifdid = $value['Catid']."<br>";
echo "Visits required per day : ".$visitsneeded= $value['Visits required']."<br>";
}
foreach(getTodaysVisits($device_id) as $rfid){
foreach($rfid as $key=> $read){
if($key ==$rifdid && $read < $visitsneeded) {
echo"<br>". $key." has not visited enough";
}
}
}
But it is not iterating through the foreach - it is only picking up the first values and then stopping :
ID: 1005
Visits required per day : 3
ID : 2089
Visits required per day : 5
2089 has not visited enough
This is the array that the foreach should be iterating through:
Array
(
[rfid_id] => Array
(
[2089] => 1
[1005] => 3
)
)
I have tried putting a variable in to count the iterations like so :
$i = 0;
foreach(getTodaysVisits($device_id) as $rfid){
foreach($rfid as $key[$i]=> $read){
if($key[$i] ==$rifdid && $read < $visitsneeded) {
echo"<br>". $key[$i]." has not visited enough";
$i++;
}
}
}
But it gives me the following errors :
Warning: Cannot use a scalar value as an array
Notice: Trying to access array offset on value of type int in
So not sure what the best course of action is, any advice greatly appreciated.

This looks like the structure that you are receiving from findCustomAlerts($customerid) in the first for-each loop is not what you are expecting, however the warnings don't give line numbers so I could be wrong.
In your code you have a $key that goes unused, then a $value that you treat as an array.
The warning message you get tells us that you can't use a scalar (or singular) value type as an array. We then get a notice telling us that when we try to use it as an array, either the offset 'Catid' or 'Visits required' is unavailable, likely due to the same reason. I suspect $value is more likely of type integer based on the array example you've shown (1,3).
Run a var_dump() on the output of the findCustomAlerts function and I think you'll understand the issue better.

Related

Sum columns and remove original indexes from multi-dimensional array [duplicate]

This question already has answers here:
Group array data on one column and sum data from another column
(5 answers)
Closed 5 months ago.
I have a php array like this:
[
['url_id' => 2191238, 'time_spent' => 41],
['url_id' => 2191606, 'time_spent' => 215],
['url_id' => 2191606, 'time_spent' => 25]
]
How to get the SUM of time_spent based on group by url_id (using array_count_values?)?
Let's pretend that $array contains our data. We will go through the array and continually add the time_spent to another array keyed by url_id.
$ts_by_url = array();
foreach($array as $data) {
if(!array_key_exists($data['url_id'], $ts_by_url))
$ts_by_url[ $data['url_id'] ] = 0;
$ts_by_url[ $data['url_id'] ] += $data['time_spent'];
}
$ts_by_url should now contain:
2191238 => 41
2191606 => 240 // == 215 + 25
The OP posted an interesting problem, but the suggestion of using array_count_values() was not applicable; the function does not sum array values but counts their frequency. The answer of #marcocassisa works but is insufficient because of the unfortunate emission of E_NOTICES, albeit unrelated to any math issue. (An undefined variable is unset and thus of NULL value, but in a math context it will temporarily be coerced into a value of zero.) Modern PHP discourages the use of undefined variables by intentionally raising notices when code utilizes them, with one exception starting with PHP 5.1: a statement consisting of only an undefined variable; see here.
To rectify the aforementioned solution, one might use two foreach loops, one to set the index keys and initialize the array elements while the other would perform the summing of values, as follows:
<?php
// set keys and initialize
foreach($arr as $data) {
$its_by_url[ $data["url_id"] ] = 0;
}
// now can sum values by url id number:
foreach($arr as $data) {
$its_by_url[ $data["url_id"] ] += $data["time_spent"];
}
see demo.
While satisfactory, this solution lacks elegance. Attempting to combine the two foreach loops into one, will negatively impact the second element, as it gets defined and then needlessly redefined. One could code per the answer of #Charles and create the url id numbered index if it doesn't already exist. Or, you could test to see if it is set, as follows:
<?php
foreach($arr as $data) {
if ( !isset( $its_by_url[ $data["url_id"] ] ) ) {
$its_by_url[ $data["url_id"] ] = 0;
}
$its_by_url[ $data["url_id"] ] += $data["time_spent"];
}
see demo
Note: if an array element were defined as null, then isset() would return false while array_key_exists() would return true. Per, Ilia Alshanetsky
... if your application does not need to distinguish between an
array key that does not exist and one whose value happens to be
NULL you should use isset() because it happens to be a little
faster.
Why not a simpler
$ts_by_url = array();
foreach($array as $data) {
$ts_by_url[ $data['url_id'] ] += $data['time_spent'];
}

Undefined offset error when iterating array after removing elements from it

I receive the following error message:
Undefined offset: 1
It points to this block of code:
$nbrProgrammingsRemoved = 0;
for($i = 0; $i<count($this->products); $i++){
if((($this->products[$i])->id)==$id){
array_splice($this->products, $i, 1);
for($j = 0; $j<count($this->programming); $j++){
/*ERROR LINE*/ if((($this->programming[$j]->out_prod_id)==$id) || (($this->programming[$j]->in_prod_id)==$id)){
$nbrProgrammingsRemoved++;
array_splice($this->programming, $j, 1);
}
}
return true;
}
}
return false;
Specifically, the error points to the innermost if-statement. (The one with "||" in it).
Now, important to note is that this error does not always occur. It only ever happens after the following code has been run:
foreach ($this->programming as $key => &$prog) {
if($prog->in_prod_id == $in_prod_id){
if($prog->in_index == $in_index){
unset($this->programming[$key]);
}
}
}
The purpose of this code is to iterate through my objects in my array and remove those associated with a certain ID. This does appear to work since the output on my website is as expected. It's only when I, after doing this, attempt to execute the first code-block that my error occurs.
I've tried troubleshooting this for a while now, but without success. Any ideas? Any more information that you need me to post?
Edit: For further clarification, if needed, the 1st code block iterates through an array to remove a single element of a specified ID. The 2nd code block iterates through another array and removes several elements.
As far as I understand, you have an array with indexes comming in a sequence:
$programming = array(
0 => ...,
1 => ...,
2 => ...,
);
At some point you unset one element, so you array looks like this:
$programming = array(
0 => ...,
2 => ...,
);
And then you're using a for loop to iterate over all numbers from 0 up to N-1 (0, 1, 2, 3, 4 ... to be precise) presuming that all indexes are filled.
I think the best solution is to use a foreach loop in this case as it will care about indexes automatically and bypass deleted items.

Trouble with extracting a value from an associative array

I am having some basics trouble with PHP. I want to retrieve an average of a column of numbers from a MYSQL database. I am using SELECT AVG() to get the result in the database. The issue is that what is returned is not a floating number but an associative array with one key:value. This is the kind of thing I am getting back in json form:
array(1) { [0]=> array(1) { ["AVG(enterpriseAppDev.employee.age)"]=> string(7) "54.4538" } }
In my PHP project I am assigning the above to a variable $average.
Can anyone tell me how I can extract the value (54.4538) the the $average variable and use it later on?
I have tried to use a foreach loop to get the value like this
foreach ($average as $x => $x_value) {
$average = $x_value;
return $average;
}
I have also tried to do the standard Deviation in SQL using STDEV and STDEVP but I get an error saying these functions do not exist.
Any help would be much appreciated.
2 problems :
you assign the value $average into the loop whereas it is in the loop parameter... can cause a crash...
so you could use return $x_value without getting it into $average.
then, you don't need a loop here just do this (with NO loop)
return $average[0]['AVG(enterpriseAppDev.employee.age)']
if you really want a loop you can do this :
foreach ($average as $line_number => $line) {
foreach($line as $key => $x_value) {
return $x_value;
}
}
1.
If you'll always get this multidimensional array you can reset the internal pointer of the array with reset to "flatten" the first one. And this should do the trick:
var_dump(reset($average[0]));
// or you can do it twice to get the same result as before
$average = reset($average);
var_dump(reset($average));
2.
But probably you can get a better key name using an alias in your SQL:
SELECT AVG() AS myavg
// so you should end up with a result like:
$queryResult = array(
array(
"myavg" => "54.4538"
)
);
// and get the average
$average = reset($queryResult);
var_dump($average['myavg']);
3.
Or even more weird, if you're using php 5.4 where you can get an array reference directly from a function result:
var_dump(reset($average)['avg']);

PHP - using foreach with array

I'm struggling to get the correct syntax to to parse out the values from an array to use with the foreach loop. I have an array:
$contacts_array
which contains one or more names which I need to search on. The array looks like this:
Array
(
[0] => PR1010
[1] => PR1086
)
If I was to manually generate the required PHP code with a known number of names it would look like this where there are 2 names to search on:
// Create first find request
$findreq1 =$fm->newFindRequest('Contacts');
// Create second find request
$findreq2 =$fm->newFindRequest('Contacts');
// Specify search criterion for first find request
$findreq1->addFindCriterion('Name', $searchTerm);
// Specify search criterion for second find request
$findreq2->addFindCriterion('Suburb', $searchTerm);;
// Add find requests to compound find command
$request->add(1,$findreq1);
$request->add(2,$findreq2);
I need to generate the equivalent code for every name in the array. I know I need to use something like:
foreach($contacts_array as $contact_array => $value)
{
}
as well as:
$num = 1
$num++; } /* foreach record */
I'm just not sure how to bring this all together so that it increments the $findreq1 variables as I go. All my attempts so far generate errors. If anyone can show me how to combine this together that would be greatly appreciated as I'm learning PHP as I go.
Thanks
<?php
for($i = 0; $i < count($contacts_array); $i++) {
${'findreq' . ($i+1)} = $fm->newFindRequest('Contacts');
${'findreq' . ($i+1)}->addFindCriterion('Name', $contacts_array[$i]);
$request->add($i+1, ${'findreq' . ($i+1)});
}
?>
Read more about Dynamic variable names in PHP
You guys beat me to it.
<?php
$contacts = Array('PR1010','PR1086');
//print_r($contacts);
foreach ($contacts as $key => $value) {
//echo "key: ".$key." - Value: ".$value."<br>";
$findreq1 = $fm->newFindRequest('Contacts');
$findreq1->addFindCriterion('Name', $value); // this is where the Array's value is passed too, it is looped for every value in the Array
$request->add(1,$findreq1);
// do more here
}
?>

PHP foreach() is amending the array

The following code which is displaying a value from within an array is presenting different results when wrapped in a foreach() as opposed to when I use a simple for-loop. The for-loop is presenting the correct data but the foreach() appears to be amending the input array with every iteration.
$arr = array_merge($arr1, $arr2);
for ($x = 0; $x < count($arr); $x++) {
echo $arr[90]['circread_value'];
}
foreach ($arr as $unused) {
echo $arr[90]['circread_value'];
}
The output from the for-loop is the same value over and over again (as expected):
1382429.00
1382429.00
1382429.00
1382429.00
...
The output from the foreach() shows that the 91st element in the array is changing with each iteration:
56256.00
45652.00
50726.00
317896.00
...
How can this be?
Note: I know the code above is contrived (obviously within the foreach() I'm actually wanting to do further processing and refer to each element of the array that I'm iterating through, not just look at the 91st element.) I have simply pared back the code to something simple (as part of my debugging, as much as for posting here!)
Some further information:
$arr has been created by array_merge'ing two 91-element arrays to create a 182 element array.
The behaviour I see is only happening for the 91st element - if I echo out $arr[89]['circread_value'] or $arr[91]['circread_value'], I get consistent values from the foreach() too.
The (seemingly random) values that I see in the foreach() are actually values from other elements in the array (the array as it looks prior to beginning the foreach)
The input arrays ($arr1 and $arr2) can be found here: http://pastebin.com/wQN8XXu2
Thanks for any insight. Don't hesitate to ask for further information.
foreach modifies the internal array pointer, for doesn't, because it expects you to supply an integer offset, as evidenced here http://us3.php.net/manual/en/control-structures.foreach.php
"As foreach relies on the internal array pointer changing it within the loop may lead to unexpected behavior."
There is something wrong with your code brother.
I've just tested this:
$arr = array(
0 => array('blah' => 123.42),
1 => array('blah' => 5488.87),
90 => array('blah' => 669874.923)
);
for ($x = 0; $x < count($arr); $x++) {
echo $arr[90]['blah'] . PHP_EOL;
}
foreach ($arr as $unused) {
echo $arr[90]['blah'] . PHP_EOL;
}
And it outputs fine:
669874.923
669874.923
669874.923
669874.923
669874.923
669874.923
Do you mind showing us a little more of your code?
Problem found. That 91st element of the array was actually a reference to the array. The foreach was then using the same variable name (reference to the same array - named $unused in the example snippet I gave in the question) so both were looking at the same array.
We noticed the "&" in the array dump after posting it on here for you guys, so StackOverflow has helped our debug process... thanks for everyone's input.

Categories