Jump to content

foreach loop overwriting all values with last key value


AdRock

Recommended Posts

I have got an array from a database and I want to change some of the values like using ucwords() etc.

 

The problem is when i run the array through a foreach loop, it overwrites all the values in the array with the values of the last row in the array.

 

I've been racking my brains all afternoon and can't figure out what's going wrong.

foreach($rows as $key => $row) {

    //$rows['datetime'] = Forum::change_date(strtotime($row['postdate']));
    $rows[$key]['board'] = strtolower(str_replace(array(' ','\''), array('-',''),$row['boardname']));
    $rows[$key]['boardid'] = $row['boardno'];
    $rows[$key]['boardname'] = ucwords($row['boardname']);
    $rows[$key]['topicname'] = Words::shortenText($row['topicname'],30);
}

I end up with the 6 rows in the array all the same.

 

Any ideas what I'm doing wrong?

Link to comment
Share on other sites

Don't try and modify the $rows array directly in the loop.  Reference $row.  Try this:

foreach($rows as &$row) {
    $row['board'] = strtolower(str_replace(array(' ','\''), array('-',''),$row['boardname']));
    $row['boardid'] = $row['boardno'];
    $row['boardname'] = ucwords($row['boardname']);
    $row['topicname'] = Words::shortenText($row['topicname'],30);
}
Link to comment
Share on other sites

I end up with the 6 rows in the array all the same.

 

 

how do you know that? perhaps your code putting the original data into the array is putting in all the same data (or retrieving all the same data in the query statement) or your code displaying the results after the code you posted above is displaying all the same result but the data in the array is correct.

 

also, why not do the processing you show above when you put the original data into the array. your current scheme has you looping over the data three times.

Link to comment
Share on other sites

you can directly iterate over the PDOStatement instance, format, and display your data, using just one foreach() loop.

 

if you are getting 6 same rows, it's likely your query is returning 6 same rows. what is your code, from your query statement through to the point where you are displaying and seeing the 6 same rows?

 

the snippet of code you posted isn't where the problem lies.

Link to comment
Share on other sites

This is the code all in the same place where i execute my query and do the foreach()

$sql = "SELECT  b.boardid as boardno, b.*, t.topicname, m.*,
        (SELECT  COUNT(*) FROM topics ti
        WHERE ti.boardid = b.boardid) AS topiccount,
        (SELECT COUNT(*) FROM topics ti, messages mi
        WHERE ti.boardid = b.boardid AND mi.topicid = ti.topicid) AS messagecount
        FROM boards b LEFT JOIN messages m ON m.messageid =
        (SELECT  mii.messageid FROM topics tii, messages mii
        WHERE tii.boardid = b.boardid AND mii.topicid = tii.topicid
        ORDER BY mii.postdate DESC LIMIT 1) LEFT JOIN topics t ON t.topicid = m.topicid ORDER BY boardname ASC LIMIT $offset, $entries_per_page";

$rows = $this->db->clean($sql);

foreach($rows as $row) {

    $rows['postdate'] = Forum::change_date(strtotime($row['postdate']));
    $rows['boardname'] = ucwords($row['boardname']);
    $rows['topicname'] = Words::shortenText($row['topicname'],30);
    $rows['board'] = strtolower(str_replace(array(' ','\''), array('-',''), $row['boardname']));
}

and this is the bit of the database class

public function clean($sql, $fetchMode = PDO::FETCH_ASSOC)
    {
        $sth = $this->query($sql);
            
        $sth->execute();
        return $sth->fetchAll();
    }

Hope you can helkp with this as it's driving me nuts

 

Link to comment
Share on other sites

What I posted will work for this scenario, but to go along with mac_gyver, use it in the loop that displays the rows:

function customize_row($row) {
    $row['postdate'] = Forum::change_date(strtotime($row['postdate']));
    $row['boardname'] = ucwords($row['boardname']);
    $row['topicname'] = Words::shortenText($row['topicname'],30);
    $row['board'] = strtolower(str_replace(array(' ','\''), array('-',''), $row['boardname']));
    
    return $row;
}

// your display code
foreach($rows as &$row) {
    $row = customize_row($row);
    // output $row stuff   
}
Link to comment
Share on other sites

Many thanks to all of you for your help.

 

I looked this morning as I wasn't convinced my foreach loop was wrong like Ch0cu3r said and I done a var_dump on the query result and saw my database array was fine and was what I expected.

 

I knew if the query was correct and the foreach was correct it must be to do with where it's being output so I looked at my foreach loop on the display page and noticed I had

 

<?php foreach($this->forum as $forumitem):?>
<div class="eW">
<div class="e1 col_1">
<h5><a href="<?php echo URL;?>forum/board/<?php echo $this->forum[0]['boardname']; ?>"><?php echo $this->forum[0]['boardname']; ?></a></h5><p><?php echo $this->forum[0]['boarddesc']; ?></p>
</div>
<div class="e2 col_2">
<p><?php echo $this->forum[0]['messagecount']; ?> Posts</p><p><?php echo $this->forum[0]['topiccount']; ?> Topics</p>
</div>
<div class="e3 col_3"> 
<?php if (!empty($forumitem[0]['topicname'])):?>
<p><b>Last post</b> by <?php echo $this->forum[0]['author']; ?></p><p>in <?php echo $this->forum[0]['topicname']; ?></p><p>on <?php echo $this->forum[0]['datetime']; ?></p>
<?php endif; ?>
</div>
</div>

It turned out and i could see that straight away from my var_dump that I needed to replace the 0 in the key value with $key and change the foreach to

<?php foreach($this->forum as $key => $forumitem):?>

As soon as I did this it worked.

 

Again many thanks for pointing me in the right direction as it would have taken me ages to figure this out not knowing if my foreach was right.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.