r0skar
r0skar

Reputation: 8696

php + Count loops + Wrong initial count?

I have a rather long code, so i think the best is I post it here with some additional comments as questions inside of it:

<div class="contentRow">

    <h2>Title</h2>

    <div id="frame">

        <?php

        //Get files
        $sql->query("SELECT * FROM files WHERE job = 'true'");
        $count  = count($sql->get());

        //No files to display
        if ($count == "0"){

            echo "<div class='box red'><p>No jobs found.</p></div>";

        } else{

            $sql->query("SELECT * FROM files WHERE job = 'true'");

            $i=0;

            foreach($sql->get() as $result){

                $i++;

        ?>

        <!-- Here I start printing the results and here the problems begin -->



        <!-- My goal here: Print n .jobsContainer with exactly 4 .jobContainer inside -->
        <?php if ($i % 4 == 0){ ?>
        </div><!-- CLOSE jobsContainer -->
        <?php } ?>

        <?php if ($i % 4 == 0 OR $i == 1){ ?>
        <div class="jobsContainer"><!-- OPEN jobsContainer -->
        <?php } ?>


            <!-- Print the .jobContainer -->
            <div class="jobContainer">
                content + table + form
            </div>

            <!-- My goal here: Print .jobSeperator after every 2nd  .jobContainer -->
            <?php if ($i % 2 == 0){ ?>
            <div class="jobSeperator">&nbsp;</div>
            <?php } ?>


        <!-- CLOSE loop -->
        <?php  } }?>


    </div><!-- jobsFrame -->

    <div class="clear"></div>

</div><!-- contentRow -->

The desired output should look like this:

enter image description here

My problem is following:

It seems that there are only 3 elements included in the first container, but after that there are 4. Therefore also the seperators are kinda messed up and it looks like this:

enter image description here

It seems that the problem is not applying to the .jobSeperator, as it does always get included after every 2th container, however it gets messed up too, because of the fact that in the first .jobsContainer there are just 3 sub containers.

I dont get why in the first .jobsContainer there are just 3 sub containers, but from than on there are, as desired, 4, but probably it is obvious and I just dont see it...

p.s. If I set the code to print 5 .jobContainer inside one .jobsContainer, than there are printed 4 in the first .jobsContainer and from than on 5 in every following .jobsContainer

Upvotes: 0

Views: 1572

Answers (4)

huysentruitw
huysentruitw

Reputation: 28151

If you inspect the generated HTML output, you'll see that when $i == 4, you first close the jobsContainer div before outputting the 4th jobContainer. You need to change the order of output to something like this:

EDIT: seems like you should split up the start of the first jobsContainer ($i == 1)

<div class="contentRow">
    <h2>Title</h2>
    <div id="frame">
        <?php
        $i = 0;
        for($j = 0; $j < 12; $j++)
        {
            $i++;
            ?>
            <?php if ($i == 1) { ?>
                <div class="jobsContainer">
            <?php } ?>

            <div class="jobContainer">job</div>

            <?php if ($i % 4 == 2) { ?>
                <div class="jobSeperator">&nbsp;</div>
            <?php } ?>

            <?php if ($i % 4 == 0) { ?>
                </div>
                <div class="jobsContainer">
            <?php } ?>

            <?php 
        }
        ?>
        <?php if ($i > 0) { ?>
            </div>
        <?php } ?>
    </div>

    <div class="clear"></div>
</div>

Upvotes: 0

Salman
Salman

Reputation: 3726

I believe You're making one small mistake.

<!-- My goal here: Print n .jobsContainer with exactly 4 .jobContainer inside -->
<?php if ( ($i+1) % 4 == 0){ ?>
</div><!-- CLOSE jobsContainer -->
<?php } ?>
<?php if ( ($i+1) % 4 == 0 OR $i == 1){ ?>
<div class="jobsContainer"><!-- OPEN jobsContainer -->
<?php } ?>

Use ($i+1) instead of $i in this bit.

Upvotes: 0

Mariusz Sakowski
Mariusz Sakowski

Reputation: 3280

try to change these lines:

    <?php if ($i % 4 == 0 OR $i == 1){ ?>
         <div class="jobsContainer"><!-- OPEN jobsContainer -->
    <?php } ?>

to

    <?php if ( ($i-1) % 4 == 0 ){ ?>
         <div class="jobsContainer"><!-- OPEN jobsContainer -->
    <?php } ?>

Now you open container at the begginning of 1st, 4th, 8th, 12th,... iteration, after this change you should open container before 1st, 5th, 9th, 13th,... iteration which should fix the problem. And you will get rid of ugly or. It seems this is the only bug, just try it.

I also suggest separating application logic and presentation.

Upvotes: 1

tereško
tereško

Reputation: 58444

First of all, you should not keep your SQL logic mixed with HTML.

Anyway. The idea is that you need to output a separator after each second item. The testcase i would look at would be like this.

1 2
---
3 4
***
5 6
---
7

And the code for writing it would be:

$i = 0;
foreach( /* some array */ as $data ){

    $i++;
    if ( ($i - 1) % 2 === 0 ){

        if ( ($i - 1) % 4 === 0 ){

            echo '<br />***<br />';
        } else {

            echo '<br />---<br />';
        }            
    }

    echo $i, ' ';
}

This would reproduce the structure above (never tested).

As for the separation of layout and rest of application logic, you might look in to this article. It will show a quite simple way, without a need of additional 3rd party libraries.

Upvotes: 1

Related Questions