Richard Graham
Richard Graham

Reputation: 45

PHP $array[]=$content not working as it ought

Okay, I have been tearing my hair (and beard) out at this one for a good hour or more now. I can't work out why it isn't working, particularly as it's exactly the same code I use elsewhere which does work.

$sql = "SELECT * FROM `aio_log` ORDER BY `log_timestamp` DESC LIMIT 10;"; // A 'WHERE' will be put in here
$logs = array();
$one_log = array();

if ($stmt = $mysqli->prepare($sql)) {
  $stmt->execute();
  $stmt->store_result();
  $stmt->bind_result($one_log['id'], $one_log['timestamp'],     $one_log['headline'],
                     $one_log['text'], $one_log['link'], $one_log['font_awesome'],
                     $one_log['type']);

  while ($stmt->fetch()) {
    if ($one_log['link'] == "") $one_log['link'] = '#';
    // print_r($one_log); shows the expected output of the database row.
    $logs[] = $one_log;
    //array_push($logs, $one_log); // gives the same - incorrect - response as the above line
  }
}
print_r($logs); // Shows the right number of returned rows from the database, but all showing
// an identical content of the last database row returned.

Probably the only difference between this code and code I've used elsewhere is that this one doesn't have any binded parts of the SQL statement as it's a simple 'select everything no matter what' statement, but as the print_r($one_log) bit works fine, I cannot see this being the issue. The issue is obviously somewhere in the $logs[] = $one_log bit, but as I've used it elsewhere, and get exactly the same result using array_push, I'm at my wits end here!

Ideas folks?

Upvotes: 1

Views: 55

Answers (1)

Barmar
Barmar

Reputation: 782498

This is very strange. The assignment

$logs[] = $one_log;

is supposed to make a copy of $one_log when it pushes it onto the array. But apparently this isn't interacting as expected with the fact that bind_param binds references to the variables -- when you fetch the new row, the references are apparently referring to the copy as well as the original. This is probably a weird consequence of the way that PHP uses copy-on-write; updating the reference seems not to be considered a write that triggers the copy.

I suggest you use normal variables instead of the $one_log array.

$stmt->bind_result($id, $timestamp, $headline, $text, $link, $font_awesome, $type);

and then in the fetch loop use:

$logs[] = array('id' => $id, 'timestamp' => $timestamp, 'headline' => $headline, 
                'text' => $text, 'link' => $link, 'font_awesome' => $font_awesome, 
                'type' => $type);

Upvotes: 3

Related Questions