Reputation: 6052
I have this PHP code, with a for loop:
$expireData = array();
for($x = 0; $x <= 10; $x++){
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from users WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
$row = $stmt->fetchAll();
#var_dump($row);
if($row["cnt"] > 0){
$expireData[] = $row["cnt"];
}else{
$expireData[] = 0;
}
}
If I do the var_dump($row)
I get:
array(2) {
[0]=>
array(4) {
["days"]=>
string(2) "27"
[0]=>
string(2) "27"
["cnt"]=>
string(1) "2"
[1]=>
string(1) "2"
}
[1]=>
array(4) {
["days"]=>
string(3) "116"
[0]=>
string(3) "116"
["cnt"]=>
string(1) "8"
[1]=>
string(1) "8"
}
}
But if I just echo $row['cnt'];
it doesn't echo anything out - it's empty. Why?
Ultimately, I wish to use the data from the for loop outside the for loop - like:
echo implode(',', $expireData);
But that just gives me
0,0,0,0,0,0,0,0,0,0
What am I doing wrong?
Upvotes: 1
Views: 1069
Reputation: 270607
Because you're using fetchAll()
to retrieve all rows into $row
, its contents are a 2 dimensional array representing multiple rows. So the key ['cnt']
is present, but is one dimension farther in your array.
$row['cnt']
doesn't exist but $row[0]['cnt']
does and $row[1]['cnt']
do exist.
The simplest solution with your current code is to move the $expireData
handling outside the loop and into a loop of its own:
$expireData = array();
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from users WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
// Load all rows into $rows rather than $row...
$rows = $stmt->fetchAll();
// Loop over all rows to populate $expireData
foreach ($rows as $row) {
if ($row["cnt"] > 0){
$expireData[] = $row["cnt"];
}else{
$expireData[] = 0;
}
}
print_r($expireData);
The other method would be to switch from fetchAll()
to plain fetch()
and append rows onto $rows
in a while loop:
// Array to hold all rows
$rows = array();
// (The outer for loop is removed...)
$stmt=$dbh->prepare("select round((expire - unix_timestamp()) / 86400) as days, count(*) as cnt from users WHERE user_by=:username group by days;");
$stmt->bindParam(":username",$userdata['username']);
$stmt->execute();
// Perform single fetch() calls in a while loop
while ($row = $stmt->fetch()) {
// Append onto array of all rows
$rows[] = $row;
// Then handle $expireData in the same loop
if ($row["cnt"] > 0){
$expireData[] = $row["cnt"];
}else{
$expireData[] = 0;
}
}
As determined in the comments, you need your final $expireData
array to have 10 values. Rather than doing that with a loop, use array_pad()
to extend it to ten and fill it with zeros.
$expireData = array_pad($expireData, 10, 0);
// turns [2,8] into [2,8,0,0,0,0,0,0,0,0]
The use of the outer for
look is suspect because it is apparently executing the same statement each time. That loop may be entirely unneeded, and all you need is its body.
The fact that you did not see PHP complaining about undefined index 'cnt'
while loading the loop suggests that you are not developing with display_errors
turned on and error_reporting
turned up. Always do so when developing and testing code. It may have helped you see the problem sooner.
At the top of your script:
error_reporting(E_ALL);
ini_set('display_errors', 1);
Upvotes: 3