PHP:重复代码行的最佳实践,没有明确的输入/输出(DRY)

I have an HMVC webapplication developed in PHP.

In my controller and in my view, I need to iterate over multiple arrays. Between the iterations I need to use/echo some values out of the array. The problem is that my code is a mess and I was wondering if there are better best practices to do this kind of loops.

For the following examples: $header has 15 values and $groups has 1000 values.

I have the following (simplified) example of code in my view:

<? foreach($headers as $header) { ?>
  <div class="header"><?= $header->number ?></div>

  <? $i = 0; ?>
  <? foreach($groups as $group) { ?>

    <? $part_letter = $group->part->letter ?>

    <? if ($group->number !== $header->number) {  continue; } ?>

    <? $i++; ?>

    <? if ($i === 1) { $first_group = true; } else { $first_group = false; } ?>

    <div class="<?= $first_group ? 'colored' : ''>
      <?= echo $group->name ?>
      <?= echo $part_letter ?>
    </div>

  <? } ?>

<? } ?>

I have the following (simplified) example of code in my controller:

foreach($headers as $header) {
  $pdf[] = $header->number;

  $i = 0;
  foreach($groups as $group) {

    $part_letter = $group->part->letter;

    if ($group->number !== $header->number) {  continue; }

    $i++;

    if ($i === 1) { $first_group = true; } else { $first_group = false; }

    $pdf['first_group'] = $first_group;
    $pdf['group_name'] = $group->name;
    $pdf['part_letter'] = $part_letter;

  }

}

My thoughts

  1. My first thought was, since the iteration in the controller and view are the same, to move this to a separate function where input would be $headers and $groups, but what would be the output? In the view I need some array values between HTML code and in the controller I need to save them in the $pdf array.
  2. My second thought was to create a separate function to iterate over both arrays to create a 3rd and 4th array with all significant values in it. That 3rd and 4th array would look something like this:

    $header_values[$id] = $number;
    $group_values[$id] = array($part_letter, $group_equals_header_number, $is_first_group);
    

    Then my controller would look like this:

    foreach($header_values as $header_value) {
      $pdf[] = $header_value;
    
      foreach($group_values as $group_value) {
    
        if (!$group_value['group_equals_header_number']) {  continue; }
    
        $pdf['first_group'] = $group_value['is_first_group'];
        $pdf['group_name'] = $group_value['group_name'];
        $pdf['part_letter'] = $group_value['part_letter'];
    
      }
    
    }
    

    And my view would look like this:

    <? if (!$group_value['group_equals_header_number']) {  continue; } ?>
    
    <div class="<?= $group_value['is_first_group'] ? 'colored' : ''>
      <?= echo $group_value['group_name'] ?>
      <?= echo $group_value['part_letter'] ?>
    </div>
    

    It looks a bit better, the downside is that I need an extra iteration.

What is best practice with this kind of repeating loops / repeating code, while keeping my code DRY?

sorry for my too quick comment, i don't have seen that the "group loop" is not a children of $header then in this case, you can waste time if you have lots of headers and lots of groups in differents headers

you can try this code, it will use a little more time for the first task but it will spare more time for the second task

<?php

////////////////////////////////////////////////////
// *** first task : grouping "groups" by header


$listHeaders = [];


// searching all the headers numbers

foreach ($headers as $header)) {
    $listHeaders[$header->number] = $header;
}


// associating groups with header

foreach ($groups as $group) {
    $headerNumber = $group->number;

    if (!isset($listHeaders[$headerNumber])) {
        continue;
    }

    if (!isset($listHeaders[$headerNumber]->listGroups)) {
        $listHeaders[$headerNumber]->listGroups = [];
    }

    $listHeaders[$headerNumber]->listGroups[] = $group;
}


////////////////////////////////////////////////////
// *** second task : display

foreach ($listHeaders as $headerNumber => $header) {

    ?>
        <div class="header">
            <?php echo $headerNumber;?>
        </div>
    <?php

    foreach ($header->listGroups as $index => $group) {

        ?>

            <div class="<?php echo (0 !== $index) ? "" : "colored";?>">
                <?php echo $group->name;?>
                <?php echo $group->part->letter;?>
            </div>

        <?php

    } // END foreach ($header->listGroups as $index => $group) {

} // END foreach ($listHeaders as $headerNumber => $header) {

just do benchmarks to choose wich code take less time with your datas