How do I show some elements of an array following this criterion?

0

I have to make a php form that in the end shows the price of each product bought, showing only the prices of the products that were marked in the other column of the table in the checkbox:

FORM:

**<!DOCTYPE html>
<html>
<head>
    <title>Pag</title>
</head>
<style>
table{
    margin-top:10%;
    width:50%;
}
.comprar{
margin-left:49%;
}
#qtd{
        width:40px;
    }
.linha1{
    text-align:center;
}
.preco{
    width: 50px;
}
</style>
<body>
<form action="cupom.php" method="post" name="compras">
<table cellspacing="5" align='center' border='1'>
<tr class="linha1"><td>Produtos</td><td>Valor Unitário</td><td>Quantidade</td></tr>

<?php
$prod['Arroz']=1.2;
$prod['Macarrão']=2.6;
$prod['Biscoito Cream']=4.1;
$prod['Margarina']=4.89;
foreach($prod as $key => $value){
   ?>
   <tr>
   <td><input type="checkbox" name="produtos[]" value="<?php echo $key; ?>"><?php echo $key; ?></td>

   <td><input type="text" name="preco[]" class="preco" readonly value="<?php echo 'R$ '.$value; ?>"></td>

   <td><input type="number" name="qtd[]" id="qtd" min="0" max="100">
   </tr>
<?php 
}
?>
</table>
<input type="submit" value="Comprar" class="comprar">
</form>
</body>
</html>**

FISCAL NOTE:

<?php
require "pag1.php";
$prod_comp = $_POST['produtos'];
$qtd_prod = $_POST['qtd'];
$precos = $_POST['preco'];
foreach($prod_comp as $value){
     echo '<p align="center">'.$value."</p>";
}
foreach($qtd_prod as $value){
     echo '<p align="center">'.$value."</p>";
}
foreach($precos as $key => $value){
     echo '<p align="center">'.$value."</p>";
}
?>
    
asked by anonymous 06.08.2017 / 01:46

1 answer

0

It is important to remember that in a form submission only the <checkbox> that are marked / selected are sent, which are not even sent. If this key is not marked, nor will it exist in $_POST['produtos'] , then this:

foreach($prod_comp as $value){
     echo '<p align="center">'.$value."</p>";
}
foreach($qtd_prod as $value){
     echo '<p align="center">'.$value."</p>";
}
foreach($precos as $key => $value){
     echo '<p align="center">'.$value."</p>";
}

It is not correct because it assumes that all exist always and $prod_comp will not always exist and will have size dependent on what was selected. In addition, $qtd_prod and $precos do not depend on what was chosen in $prod_comp .

Instead we can change the html of <checkbox> to have a sequential numeric value:

$prod['Margarina']=4.89;
$num = 0; //numero do produto
foreach($prod as $key => $value){
   ?>
   <tr>
   <td><input type="checkbox" name="produtos[]" value="<?=$num++?>"><?php echo $key; ?></td>

   ...
<?php 
}

What will make the html generated for <checkbox> look like this:

<td><input type="checkbox" name="produtos[]" value="0">Arroz</td>
<td><input type="checkbox" name="produtos[]" value="1">Macarrão</td>
<td><input type="checkbox" name="produtos[]" value="2">Biscoito Cream</td>
<td><input type="checkbox" name="produtos[]" value="3">Margarina</td>

In this way when submitted, by value we know which lines we need to read to other arrays. We can then interpret as follows:

if ($_SERVER["REQUEST_METHOD"] == "POST"){ //se foi submetido em post

    if (isset($_POST["produtos"])){ //se existem produtos escolhidos

        //criar os nomes num array
        $nomesProdutos = array('Arroz','Macarrão','Biscoito Cream','Margarina'); 

        //obter todos os arrays que vem de $_POST como já era feito
        $prod_comp = $_POST['produtos'];
        $qtd_prod = $_POST['qtd'];
        $precos = $_POST['preco'];

        echo "Produtos escolhidos:";

        //for apenas sobre os que foram escolhidos
        for ($i = 0; $i < count($prod_comp);++$i){
            $pos = $prod_comp[$i]; //obter a posição do elemento escolhido (0,1,2 ...)
            //ir buscar as informações aos outros arrays com base nessa posição
            echo "Nome:  $nomesProdutos[$pos]  Quantidade: $qtd_prod[$pos] Preço: $precos[$pos]<br>";
        }
    }
    else {
        echo "Não escolheu nenhum produto";
    }
}

This solution already works for the intended purpose. A more organized solution would be to use classes because we have 3 distinct arrays that refer to the same thing, a product. For this reason we could create a Produto class and create objects of that class within for :

class Produto{
    var $nome;
    var $quantidade;
    var $preco;

    //construtor de Produto que recebe nome, quantidade e preço
    function __construct($nome, $quantidade, $preco){
        $this->nome = $nome;
        $this->quantidade = $quantidade;
        $this->preco = $preco;
    }
}


if ($_SERVER["REQUEST_METHOD"] == "POST"){

    if (isset($_POST["produtos"])){

        $nomesProdutos = array('Arroz','Macarrão','Biscoito Cream','Margarina');

        $prod_comp = $_POST['produtos'];
        $qtd_prod = $_POST['qtd'];
        $precos = $_POST['preco'];

        echo "Produtos escolhidos:";

        //Array de objetos produto
        $produtos = array();

        for ($i = 0; $i < count($prod_comp);++$i){
            $pos = $prod_comp[$i];
            //acrescentar um novo objeto produto ao array
            $produtos[] = new Produto($nomesProdutos[$pos], $qtd_prod[$pos], $precos[$pos]);
        }

        //mostrar todos
        print_r($produtos);
    }
    else {
        echo "Não escolheu nenhum produto";
    }
}

It would however make sense to create a specific method to be able to show Produto in html in a more beautiful and organized way, so that the visualization would be identical to the classless code. This method might look like this:

class Produto{
    ...
    //método para obter o html do produto de forma mais organizada
    function obterHtml(){
        return "Nome:  {$this->nome}  Quantidade: {$this->quantidade} Preço: {$this->preco}<br>";
    }
}

And now we show you where you need to by just calling the method:

//mostrar todos
foreach ($produtos as $prod){
    echo ($prod->obterHtml());
}

As an additional note, there is a small flaw in html that has a closing tag </td> missing in:

<td><input type="number" name="qtd[]" id="qtd" min="0" max="100">
   </tr>

That should be fixed for

<td><input type="number" name="qtd[]" id="qtd" min="0" max="100"></td>
   </tr>
    
06.08.2017 / 15:01