How to predict next results from an array within the foreach

Asked

Viewed 78 times

0

Well I have the following code:

    // Aqui eu recebos os produtos da API
$produtos = array(
    array('cod' => 8, 'nome' => 'Produto teste 8', 'grupo' => 'Doces', 'valor' => 1007),
    array('cod' => 9, 'nome' => 'Produto teste 9', 'grupo' => 'Doces', 'valor' => 1050),
    array('cod' => 10, 'nome' => 'Produto teste 10', 'grupo' => 'Doces', 'valor' => 1050),
    array('cod' => 1, 'nome' => 'Produto teste 1', 'grupo' => 'Farinha', 'valor' => 1400),
    array('cod' => 2, 'nome' => 'Produto teste 2', 'grupo' => 'Farinha', 'valor' => 170),
    array('cod' => 4, 'nome' => 'Produto teste 4', 'grupo' => 'Frios', 'valor' => 1600),
    array('cod' => 5, 'nome' => 'Produto teste 5', 'grupo' => 'Frios', 'valor' => 1800),
    array('cod' => 6, 'nome' => 'Produto teste 6', 'grupo' => 'Frios', 'valor' => 1070),
    array('cod' => 7, 'nome' => 'Produto teste 7', 'grupo' => 'Frios', 'valor' => 1070),
    array('cod' => 11, 'nome' => 'Produto teste 11', 'grupo' => 'Frios', 'valor' => 1060),
    array('cod' => 3, 'nome' => 'Produto teste 3', 'grupo' => 'Limpeza', 'valor' => 1080)
);

//OBS o array esta em ordem alfabétida dos grupos


// Aqui eu monto o HTML
?>
<table>

    <tbody>
        <?php

        // Inicía variável
        $categoriaAtual = null;

        // Navega pelos elementos do array
        foreach ($produtos as $c) {

            // Verifica grupo
            if ($categoriaAtual !== $c['grupo']) {

                $categoriaAtual = $c['grupo'];

                ?>
                <thead>
                    <tr>
                        <td colspan="100%">
                            <b><i><?=$c['grupo']?></i><b>
                        </td>
                    </tr>
                    <tr>
                        <td>Cód. Produto</td>
                        <td>Produto</td>
                        <td>Valor</td>
                    </tr>
                </thead>
                <?php
            }
            ?>
            <tr>
                <td><?= $c['cod'] ?></td>
                <td><?= $c['nome'] ?></td>
                <td><?= $c['valor'] ?></td>
            </tr>
            <?php
        }
        ?>
    </tbody>
</table>

The result is this:

Doces
Cód. Produto	Produto	Valor
8	Produto teste 8	1007
9	Produto teste 9	1050
10	Produto teste 10	1050
Farinha
Cód. Produto	Produto	Valor
1	Produto teste 1	1400
2	Produto teste 2	170
Frios
Cód. Produto	Produto	Valor
4	Produto teste 4	1600
5	Produto teste 5	1800
6	Produto teste 6	1070
7	Produto teste 7	1070
11	Produto teste 11	1060
Limpeza
Cód. Produto	Produto	Valor
3	Produto teste 3	1080

Well I want to add at the end of each group the total, thought to do this by detecting when is the last product of the group and adding a <tr>

Does anyone know how to do that? Or even in a more practical way?

  • And what would be the need for this? If the need is what I imagine then the strategy would be 2 loops, but I can’t say without details, the good thing about explaining this in the question is that sometimes you think you need something that you don’t really need and so we can give better suggestions that address your problem.

  • I edited the question in more detail

  • You could do the foreach with as $i => $functionario and display the salary of $functionarios[$i+1], with the appropriate conditions, but also did not understand very well the objective, mainly in relation to the product group being the example with employees.

  • Could you give a real example? I believe two people answered the question without clarifying your question. Since you speak in grouped products (therefore I understand that there are multiple groups), but your code treats a list of employees without grouping...

  • @bfavaretto de fata is true, I edited the question with a real example

  • If it is the total, then simply iterate will not solve fully, has to add, but can do in a single is, I will try to do here and put in the answer

  • I will withdraw the answer for now because I have no way to analyze at the moment. When you are more relaxed I give a feedback.

  • Hugo e @Augustovasques editei https://answall.com/a/435115/3635, simplified for an IF, the important part, which is now evident, was the sum of the values, had problems in HTML markup, I made some adjustments, about semantics I do not know if it is OK, but the logic without needing 2 "for"s gave to adjust, I will comment on the code to be clearer.

Show 3 more comments

1 answer

3


Before answering I need to warn you, your Theads are being generated on the same level as the other Trs that do not belong to the Theads themselves, there should be a TBODY in each, but the main problem is that you have put everything inside TBODY, but it is likely that the renderer "correct".

Your problem goes beyond adding a line, it has to add up the values, keeping this in mind it is necessary 2 auxiliary variables, a kind you have already made $categoriaAtual = null;, but the sum of.

Another thing, if you are going to mix so much HTML with PHP I would personally choose to use this format:

<?php if (): ?>
html
<?php endif; ?>

and

<?php for/while/foreach (): ?>
<?php endfor/endwhile/endforeach; ?>

There is no gain in performance, the question just improve a little as you see the code, overall it should look like this:

<?php

$produtos = array(
    array('cod' => 8, 'nome' => 'Produto teste 8', 'grupo' => 'Doces', 'valor' => 1007),
    array('cod' => 9, 'nome' => 'Produto teste 9', 'grupo' => 'Doces', 'valor' => 1050),
    array('cod' => 10, 'nome' => 'Produto teste 10', 'grupo' => 'Doces', 'valor' => 1050),
    array('cod' => 1, 'nome' => 'Produto teste 1', 'grupo' => 'Farinha', 'valor' => 1400),
    array('cod' => 2, 'nome' => 'Produto teste 2', 'grupo' => 'Farinha', 'valor' => 170),
    array('cod' => 4, 'nome' => 'Produto teste 4', 'grupo' => 'Frios', 'valor' => 1600),
    array('cod' => 5, 'nome' => 'Produto teste 5', 'grupo' => 'Frios', 'valor' => 1800),
    array('cod' => 6, 'nome' => 'Produto teste 6', 'grupo' => 'Frios', 'valor' => 1070),
    array('cod' => 7, 'nome' => 'Produto teste 7', 'grupo' => 'Frios', 'valor' => 1070),
    array('cod' => 11, 'nome' => 'Produto teste 11', 'grupo' => 'Frios', 'valor' => 1060),
    array('cod' => 3, 'nome' => 'Produto teste 3', 'grupo' => 'Limpeza', 'valor' => 1080)
);
?>

<table>
    <?php
    // Inicía variável
    $categoriaAtual = null;
    $categoriaTotal = 0;
    ?>

    <?php foreach ($produtos as $produto): ?>

        <?php if ($categoriaAtual !== $produto['grupo']): ?>


        <?php
        // Entra neste IF se não for o primeiro produto, devido ao NULL inicial
        if ($categoriaAtual !== null):
        ?>

        <tr>
            <td colspan="2">Total</td>
            <td><?=$categoriaTotal?></td>
        </tr>

        <?php
        // Quando muda de categoria é necessário "resetar" a soma para poder começar novamente
        $categoriaTotal = 0;
        ?>

        </tbody>

        <?php endif; ?>

        <thead>
            <tr>
                <td colspan="100%">
                    <b><i><?=$produto['grupo']?></i><b>
                </td>
            </tr>
            <tr>
                <td>Cód. Produto</td>
                <td>Produto</td>
                <td>Valor</td>
            </tr>
        </thead>
        <?php endif; ?>

        <?php
        //Seta o valor sempre, para o proximo ciclo poder saber se o grupo mudou
        $categoriaAtual = $produto['grupo'];

        //Soma os valores a cada ciclo
        $categoriaTotal += $produto['valor'];
        ?>

        <tr>
            <td><?= $produto['cod'] ?></td>
            <td><?= $produto['nome'] ?></td>
            <td><?= $produto['valor'] ?></td>
        </tr>

    <?php endforeach; ?>

    <?php
    //Nesta parte o foreach já terminou, mas é necessário pegar o total
    //do ultimo grpo e fechar o TBODY e isto só pode ocorrer se tiver ao
    //menos um produto no array, se tiver zero nem entra neste IF
    if ($categoriaAtual !== null):
    ?>
        <tr>
            <td colspan="2">Total</td>
            <td><?=$categoriaTotal?></td>
        </tr>

        </tbody>
    <?php endif; ?>

</table>

To see the result put in Stacksnipet below:

table {
    width: 100%;
}

td {
    border: 1px solid #ccc;
}

thead {
    background: #00f;
    color: #fff;
}
<table>
    
    
                
        <thead>
            <tr>
                <td colspan="100%">
                    <b><i>Doces</i><b>
                </td>
            </tr>
            <tr>
                <td>Cód. Produto</td>
                <td>Produto</td>
                <td>Valor</td>
            </tr>
        </thead>
        
        
        <tr>
            <td>8</td>
            <td>Produto teste 8</td>
            <td>1007</td>
        </tr>

    
        
        
        <tr>
            <td>9</td>
            <td>Produto teste 9</td>
            <td>1050</td>
        </tr>

    
        
        
        <tr>
            <td>10</td>
            <td>Produto teste 10</td>
            <td>1050</td>
        </tr>

    
                
        <tr>
            <td colspan="2">Total</td>
            <td>3107</td>
        </tr>

        
        </tbody>

        
        <thead>
            <tr>
                <td colspan="100%">
                    <b><i>Farinha</i><b>
                </td>
            </tr>
            <tr>
                <td>Cód. Produto</td>
                <td>Produto</td>
                <td>Valor</td>
            </tr>
        </thead>
        
        
        <tr>
            <td>1</td>
            <td>Produto teste 1</td>
            <td>1400</td>
        </tr>

    
        
        
        <tr>
            <td>2</td>
            <td>Produto teste 2</td>
            <td>170</td>
        </tr>

    
                
        <tr>
            <td colspan="2">Total</td>
            <td>1570</td>
        </tr>

        
        </tbody>

        
        <thead>
            <tr>
                <td colspan="100%">
                    <b><i>Frios</i><b>
                </td>
            </tr>
            <tr>
                <td>Cód. Produto</td>
                <td>Produto</td>
                <td>Valor</td>
            </tr>
        </thead>
        
        
        <tr>
            <td>4</td>
            <td>Produto teste 4</td>
            <td>1600</td>
        </tr>

    
        
        
        <tr>
            <td>5</td>
            <td>Produto teste 5</td>
            <td>1800</td>
        </tr>

    
        
        
        <tr>
            <td>6</td>
            <td>Produto teste 6</td>
            <td>1070</td>
        </tr>

    
        
        
        <tr>
            <td>7</td>
            <td>Produto teste 7</td>
            <td>1070</td>
        </tr>

    
        
        
        <tr>
            <td>11</td>
            <td>Produto teste 11</td>
            <td>1060</td>
        </tr>

    
                
        <tr>
            <td colspan="2">Total</td>
            <td>6600</td>
        </tr>

        
        </tbody>

        
        <thead>
            <tr>
                <td colspan="100%">
                    <b><i>Limpeza</i><b>
                </td>
            </tr>
            <tr>
                <td>Cód. Produto</td>
                <td>Produto</td>
                <td>Valor</td>
            </tr>
        </thead>
        
        
        <tr>
            <td>3</td>
            <td>Produto teste 3</td>
            <td>1080</td>
        </tr>

    
            <tr>
            <td colspan="2">Total</td>
            <td>1080</td>
        </tr>

        </tbody>
    
</table>

Answer before editing

If you know how many items an array/iterator has, then you know when the last one will actually be, even before the foreach you and the "script" already know when should be the last, just increment a variable from scratch like this:

<?php

$funcionarios = array(
    array('id' => 1, 'nome' => 'João', 'salario' => 5000),
    array('id' => 22, 'nome' => 'Mauro', 'salario' => 560),
    array('id' => 8, 'nome' => 'Alice', 'salario' => 4300),
);

$j = count($funcionarios);

for ($i = 0; $i < $j; ++$i) {

    if ($j - 1 === $i) {
        //Aqui vai a tal linha sobre o ultimo resultado
    }

    $funcionario = $funcionarios[$i];

    echo $funcionario["nome"]." $".$funcionario["salario"]."<br>\n";

    // Aqui quero colocar o proximo resultado
}

Now if the data came from a bank, then I suppose you used fetchAll of PDO supports Count and in foreach with PDO can apply within the scope a ++$i

If mysqli API can use num_rows() (or SELECT FOUND_ROWS(); in a query, depending on what you did) before iterating.

  • 1

    Look at the comment I left now on the question. I believe the real doubt is another (according to the last paragraph of the question). cc @Augustovasques

  • @bfavaretto is just put the IF before then. Lack of attention from my.

  • It seems that he wants to group the data in the background

  • 1

    @bfavaretto so is, and also had the sum of the values, he had not informed clearly, edited and left an example of the output in HTML.

  • Very good, I managed to do exactly what I wanted.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.