phphtmlif-statementwhile-loop

New containing div after every 3 records


I would like to create a new containing <div> after 3 results, using PDO result loop.

For my self-study-project I have to made a product page with bootstrap and after every 3rd record I have to make a new row and show again 3 col-md-4's, etc, etc.

Now I have this as my code:

<div class="row">
    <?php
    while ($row = $stmt->fetch(PDO::FETCH_OBJ)) {
    ?>
        <div class="col-md-4">
            <div class="product">
                <div class="title"><?php echo $row->pname ?></div>
                <div class="img"><img
                    src="../product/img/<?php echo $row->pnumber ?>/<?php echo $row->pthumbnail ?>.jpg?$pop210x210$"/>
                </div>
                <div class="vijftien"></div>
                <div class="deliver">Levertijd: <strong><?php echo $row->pdelivertime ?></strong></div>
                <div class="vijf"></div>
                <div class="other"></div>
                <div class="row">
                    <div class="col-md-6">
                        <div class="price"><?php echo $row->pprice ?></div>
                    </div>
                    <div class="col-md-6">
                        <div class="order">
                            <button class="log_in" id="doLogin">Meer informatie</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    <?php } ?>
</div>

I have visited and studied other questions but I do not really get the idea of how they are doing it and how I can implement the correct method into my code.


Solution

  • As tadman stated in the comment under your question. The best approach should use a modulus operator (%) with 3.

    Place your separating condition at the start of each iteration. (Demo)

    Like this:

    $x = 0;  // I prefer to increment starting from zero.
             // This way I can use the same method inside a foreach loop on
             // zero-indexed arrays, leveraging the keys, and omit the `++` line.
    echo "<div class=\"row\">";
        foreach ($rows as $row) {
            if ($x != 0 && $x % 3 == 0) {  // if not first iteration and iteration divided by 3 has no remainder...
                echo "</div>\n<div class='row'>";
            }
            echo "<div>$row</div>";
            ++$x;
        }
    echo "</div>";
    

    This will create:

    <div class="row"><div>one</div><div>two</div><div>three</div></div>
    <div class='row'><div>four</div><div>five</div><div>six</div></div>
    

    Late Edit, here are a couple of other methods for similar situations which will provide the same result:

    foreach (array_chunk($rows, 3) as $a) {
        echo "<div class=\"row\"><div>", implode('</div><div>', $a), "</div></div>\n";
    }
    

    or

    foreach ($rows as $i => $v) {
        if ($i % 3 == 0) {
            if ($i != 0) {
                echo "</div>\n";
            }
            echo "<div class=\"row\">";
        }
        echo "<div>$v</div>";
    }
    if ($rows) {
        echo "</div>";
    }
    

    To clarify what NOT to do...

    Sinan Ulker's answer will lead to an unwanted result depending on the size of your result array.

    Here is a generalized example to expose the issue:

    Using this input array to represent your pdo results:

    $rows = ["one", "two", "three", "four", "five", "six"];
    

    Sinan's condition at the end of each iteration:

    $i = 1;
    echo "<div class=\"row\">";
        foreach ($rows as $row) {
            echo "<div>$row</div>";
            if ($i % 3 == 0) echo "</div>\n<div class='row'>";  // 6 % 3 == 0 and that's not good here
            // 6 % 3 == 0 and will echo the close/open line after the content to create an empty, unwanted dom element
            $i++;
        }
    echo "</div>\n\n";
    

    Will create this:

    <div class="row"><div>one</div><div>two</div><div>three</div></div>
    <div class='row'><div>four</div><div>five</div><div>six</div></div>
    <div class='row'></div>                          //<--- this extra element is not good