1

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?

8
  • 4
    Note that $row is a 2D array because you used fetchAll(). So $row['cnt'] doesn't exist but $row[0]['cnt'] does and $row[1]['cnt'] does. Commented Nov 4, 2014 at 19:08
  • OK, maybe I'm blind, but where is the for each? Commented Nov 4, 2014 at 19:09
  • Sorry - for() statement. @MichaelBerkowski so how do I use it outside the for() scope? Commented Nov 4, 2014 at 19:10
  • $row[0]['cnt']. Your $row variable is an Array with array inner. Commented Nov 4, 2014 at 19:12
  • 2
    You know you are making the same IDENTICAL request 10 times right? Commented Nov 4, 2014 at 19:12

1 Answer 1

3

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

Pad the array to 10 values:

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]

Notes on the for loop:

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.

Notes on error reporting:

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);
Sign up to request clarification or add additional context in comments.

15 Comments

Fixed that fetchAll() for you, hope you don’t mind.
No problem, i also think you should remove that for loop since this is heading for an accepted answer and could probably confuse people who read through the lines and just go for the answer in the future.
I tried using the second method, in where you removed the outer loop. Although I need to run the code 10 times - since I need 10x data to output (even if it's just a '0').
@MichaelBerkowski If you could provide the original answer with the for loop, I would be grateful. Since as said, I need it to loop through the data
@oliverbj You need 10 values in $expireData? The original one was executing the exact same query 10 times. How many rows does the query return?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.