Closing </div> Tag Is Being Outputted To Early In A While Loop - PHP

Viewed 28

I have an image board preview that outputs the first 4 images from a user's image library. Within the while loop an $imgcount happens to ensure a maximum of 4 images can be outputted.

After 4 images are outputted a closing </div> tag is meant to be outputted after the final <img> tag to close off the .board-component.

If the user has any further image boards these are then outputted within the while loop in the same context.

The Problem

The closing </div> tag is being outputted after the first image, and then the 3 subsequent images are outputted before the next .board-component div is outputted.

I've included a representation of what is happening, and what should happen below the initial code.

Note: I'm not getting any PHP errors, and I think it is purely a conditional logic error.

<div class="column">
    <?php

        $s = "SELECT boards.board_name, boards.board_id, images.filename
        FROM boards
        INNER JOIN boards_images ON boards_images.board_id = boards.board_id
        INNER JOIN images        ON boards_images.image_id = images.image_id
        WHERE boards.user_id = :user_id";

        $stmt = $connection->prepare($s);
        $stmt -> execute([
            ':user_id' => $db_id  // $db_id is from a $_SESSION login value
        ]);

        $dbBoardname_last = '';
        $imgcount = 0;

        while ($row = $stmt->fetch()) {

            $dbBoardname = htmlspecialchars($row['board_name']);
            $dbImageFile = "$wwwRoot/images-lib/" . htmlspecialchars($row['filename']);

            //if the board name is the same as the previous $row only add images. 
            if($dbBoardname != $dbBoardname_last) {

                //reset the image count for new boards
                $imgcount = 0;

                echo "
                <div class='board-component'>
                    <h2>{$dbBoardname}</h2>
                ";
            }

            // if less than 4 images   
            if($imgcount < 4) { 
                echo "
                <img src='{$dbImageFile}'>
                ";
            }

            $imgcount+=1;
            
            // close the board component div
            if($dbBoardname != $dbBoardname_last) {
                echo "
                </div>
                ";
            }
            //record the last board_name to check if a new board element should be created
            $dbBoardname_last = $dbBoardname;
        } 
    ?>
</div>

The output that is happening:

<div class='board-component'>
    <h2>The Board Name</h2>
    <img src="path/to/image1.jpg">
</div> <!-- the component closes here after the 1st image, instead of after the 4th image -->
<img src="path/to/image2.jpg">
<img src="path/to/image3.jpg">
<img src="path/to/image4.jpg">

<div class='board-component'> <!-- next board component -->
...

What is meant to happen:

<div class='board-component'>
    <h2>The Board Name</h2>
    <img src="path/to/image1.jpg">
    <img src="path/to/image2.jpg">
    <img src="path/to/image3.jpg">
    <img src="path/to/image4.jpg">
</div> <!-- the component should close here -->

<div class='board-component'> <!-- next board component -->
...
1 Answers

The condition for closing the board component div is the same as the condition for starting a new div, so you always close the div immediately after starting.

You need to close the previous div right before you open a new div. This just needs an extra check for the first iteration, so it doesn't close a div that was never opened.

Then you need to close the last div after the loop is finished. This also needs to check that there was a previous board, in case the query returns no rows so there's nothing to close.

        while ($row = $stmt->fetch()) {

            $dbBoardname = htmlspecialchars($row['board_name']);
            // close the previousboard component div
            if($dbBoardname_last != '' && $dbBoardname != $dbBoardname_last) {
                echo "
                </div>
                ";
            }
            $dbImageFile = "$wwwRoot/images-lib/" . htmlspecialchars($row['filename']);

            //if the board name is the same as the previous $row only add images. 
            if($dbBoardname != $dbBoardname_last) {

                //reset the image count for new boards
                $imgcount = 0;

                // close the previous board component div
                if ($dbBoardname_last != '') {
                    echo "
                    </div>
                    ";
                }
                echo "
                <div class='board-component'>
                    <h2>{$dbBoardname}</h2>
                ";
            }

            // if less than 4 images   
            if($imgcount < 4) { 
                echo "
                <img src='{$dbImageFile}'>
                ";
            }

            $imgcount+=1;
            
            //record the last board_name to check if a new board element should be created
            $dbBoardname_last = $dbBoardname;
        }
        // close the last board component div
        if ($dbBoardname_last != '') {
            echo "
            </div>
            ";
        }

Another thing: You should use ORDER BY boards.board_name in the query, so all the rows for the same board will be grouped together.

Related