PHP计数循环添加额外的行

I'm trying to wrap every 3 articles in a div so that my HTML would like like this:

<div class="row">
  <article>Article One</article>
  <article>Article Two</article>
  <article>Article Three</article>
</div>
<div class="row">
  <article>Article Four</article>
  <article>Article Five</article>
  <article>Article Six</article>
</div>

Below is my PHP. This is what I currently have, however an extra row is being added at the beginning, which I do not want.

$i = 0;
echo '<div class="row">';
if ($my_query->have_posts()) : 
while ($my_query->have_posts()) : $my_query->the_post(); ?>
<?php if($i % 3 == 0) {echo '</div><div class="row">';}?>

The above prints the following:

<div class="row"></div> //I don't want this to be in the HTML
<div class="row">
  <article>Article One</article>
  <article>Article Two</article>
  <article>Article Three</article>
</div>
<div class="row">
  <article>Article Four</article>
  <article>Article Five</article>
  <article>Article Six</article>
</div>

I tried changing $i = 0 to $i = 1 but this didn't work either. This prints this in the markup:

    <div class="row">
      <article>Article One</article>
      <article>Article Two</article>
    </div>
    <div class="row">
      <article>Article Three</article>
      <article>Article Four</article>
      <article>Article Five</article>
    </div>
    <div class="row">
      <article>Article Six</article>
    </div>

I've tried different number combinations but I couldn't seem to get it simply wrap every 3 articles.

Write your condition as below:-

if(!empty($i) && $i % 3 == 0)

For this kind of thing, I usually find it easier to create an array of HTML elements and to print them, whenever it's needed. It would be something like this:

$listItems = array();
if ($my_query->have_posts()) {
    while ($my_query->have_posts()) {
        $my_query->the_post();

        // Convert the post to <article>...</article>
        // and put the result in $articleHtml

        $listItems[] = $articleHtml;

        if (count($listItems) === 3) {
            // We have 3 items - print them
            echo '<div class="row">' . implode('', $listItems) . '</div>';
            $listItems = array();
        }
    }
}

// Don't forget the last items
if (count($listItems)) {
    echo '<div class="row">' . implode('', $listItems) . '</div>';
}

Let's analyze the requirement first and make a plan.

Since you need to wrap every three items in a <div>, the <div> open tag must be produced before each group of three and the </div> closing tag after each group of three. Before a group of three means "before the first article that follows zero or more groups of three".

Special care must be taken for the last group. If it is complete then the closing tag was already produced during the loop, otherwise it have to be generated after the loop.

Let's write the code now:

// $i always count how many articles were already displayed
// none yet
$i = 0;
if ($my_query->have_posts()) {
    while ($my_query->have_posts()) {
        if ($i % 3 == 0) {
            // $i is multiple of three
            // Zero or more complete groups were already displayed
            // Start a new group
            echo '<div class="row">';
        }

        // Display the current article and count it
        $my_query->the_post();
        $i ++;

        // After each group of three, close the group
        if ($i % 3 == 0) {
            // A multiple of three articles was displayed; close the group
            echo '</div>';
        }
    }

    // If the last group is not complete then must close it now
    if ($i % 3 != 0) {
        // The last group contains 1 or 2 articles; it was not closed yet
        echo '</div>';
    }
}