foreach gravando varias vezes no BD

Enviada por Roberto C 
Roberto C
foreach gravando varias vezes no BD
12 de April de 2017 às 02:45PM
Pessoal to fazendo um formulário de entrada de produtos (espelho da NF) que tem a opção de clonar as linhas para incluir mais produtos.

Esse formulário grava em 2 tabelas 1º cabeçalho da NF e a 2º grava os detalhes onde tem o ID do produto a quantidade o valor unitário o valor total e o ID do cabeçalho para isso uso o LAST_INSERT_ID()

Só que estou com um problema montei o foreach conforme abaixo quando tenho apenas uma linha no formulário mas quando tem mais de um item ele fica doido, grava diversas vezes no banco com dados incorretos e a partir da segunda linha ele perde o LAST_INSERT_ID()

Onde estou errando?

foreach($_POST["cat_id"] as $cat_id)
foreach($_POST["qtd"] as $qtd)
foreach($_POST["valor_unid"] as $valor_unid)
foreach($_POST["valor_total"] as $valor_total)

mysql_query("INSERT INTO lc_detalhe (cat_id,qtd,valor_unid,valor_total,controle_id) values
('$cat_id','$qtd','$valor_unid','$valor_total',LAST_INSERT_ID())");


e o formulário

<table border="0" cellpadding="2" cellspacing="4">
<tr>
<td class="bd_titulo">ID</td><td class="bd_titulo">Produto</td><td class="bd_titulo">Quantidade</td><td class="bd_titulo">Valor Unitario</td><td class="bd_titulo">Valor Total</td></tr>
<tr class="linhas">
<td><input type="text" name="id" style="text-align:center" disabled="true" /></td>
<td><select name="cat_id[]">
<?php
while ($row=mysql_fetch_array($qr)){
?>
<option value="<?php echo $row['id']?>"><?php echo $row['nome']?></option>
<?php }?></td>
<td>
<input type="text" name="qtd[]" class="qtd" required name="qtd"
style="text-align:center" />
</td>
<td>
<input name="valor_unid[]" type="text" required name="valor_unid"
maxlength="30"
onblur="Calc(this)"
class="valor_unid" />
</td>
<td>
<input type="text" name="valor_total[]"
class="vtotal" readonly="readonly"
style="text-align:center"/>
</td>
<td><a href="#" class="removerCampo" title="Remover linha"><img src="img/excluir.jpg" border="0" /></a></td>
</tr>
<tr><td colspan="4">
<a href="#" class="adicionarCampo" title="Adicionar item"><img src="img/+.jpg" border="0" /></a>
</td></tr>
<tr>
<p><input type="submit" value="Cadastrar" /></p>
Jayme A. C. Gimenez
Re: foreach gravando varias vezes no BD
12 de April de 2017 às 07:29PM
Grandes progressos! Parece estar quase lá.

Para extrair os dados de dois ou mais arrays de forma que esses dados fiquem pareados pela chave (key), você tem que fazer algo assim:

if(isset($array1)) {
foreach($array1 as $key => $valor1) {
$valor2 = isset($array2[$key])?$array2[$key]:null;
$valor3 = isset($array3[$key])?$array3[$key]:null;
echo "linha $key = valor1=> $valor1, valor2=> $valor2, valor3=> $valor3<br />";
}
}

Fiz direto aqui e ainda pode ter todo tipo de erro, claro. Qualquer coisa, grita! (aquele echo é só para caso você queira testar para ver se os dados estão sendo extraídos como esperado; no seu script, ele não seria usado).
Felipe
Re: foreach gravando varias vezes no BD
12 de April de 2017 às 09:16PM
Roberto C Escreveu:
-------------------------------------------------------
> Pessoal to fazendo um formulário de entrada de
> produtos (espelho da NF) que tem a opção de
> clonar as linhas para incluir mais produtos.

Cara, fugindo um pouco da questão, você já pensou em automatizar esse "espelho da NF" importando via XML?
Uma vez que vc tem a chave de acesso da NFE, você pode solicitar ao emitente o XML ou simplesmente baixá-lo no portal da NFe (Requer o certificado digital da empresa destinatária, que por motivos óbvios é a sua empresa).

Se você pesquisar manipulação de XML por alguns minutos, vai ver que é muito mais fácil do que costumamos pensar.

Faça um formulário com input pra fazer upload do XML e então comece a manipulá-lo direto no PHP x Banco de dados.

PS: A função mysql_query foi depreciada no php e já não funciona no PHP 7. Comece a utilizar o mysqli ou PDO(Recomendado) para evitar alterar todo o seu projeto!
Roberto C Escreveu:
-------------------------------------------------------
> mysql_query("INSERT INTO lc_detalhe (cat_id,qtd,valor_unid,valor_total,controle_id) values
> ('$cat_id','$qtd','$valor_unid','$valor_total',LAST_INSERT_ID())");
Roberto C
Re: foreach gravando varias vezes no BD
13 de April de 2017 às 12:35PM
Jayme....valeu pela dica...to aprendendo bastante...

coloquei o array como vc explicou mas continua gravando varias vezes no banco e perdendo o LAST_INSERT_ID() do insert anterior.

Olha como coloquei me da uma dica se está correto por favor.

mysql_query("INSERT INTO lc_controle (dia, mes, ano, dtConcat, clienteVa, clienteAt, userml, rastreador, entrega, total, frete, frete_real, nf, origem, tipo_pagto, descricao, tipo, tipo_venda) values
('$dia', '$mes', '$ano', '$dtConcat', '$clienteVa', '0', '$userml', '$rastreador', '$entrega', '$total', '$frete', '$frete_real', '$nf', '$origem', '$tipo_pagto', '$descricao','0','Varejo')");

foreach($_POST["cat_id"] as $cat_id)
foreach($_POST["qtd"] as $qtd)
foreach($_POST["valor_unid"] as $valor_unid)
foreach($_POST["valor_total"] as $valor_total)

mysql_query("INSERT INTO lc_detalhe (cat_id,qtd,valor_unid,valor_total,controle_id) values
('$cat_id','$qtd','$valor_unid','$valor_total',LAST_INSERT_ID())");

if(isset($array1)) {
foreach($array1 as $key => $cat_id) {
$valor2 = isset($array2[$key])?$array2[$qtd]:null;
$valor3 = isset($array3[$key])?$array3[$valor_unid]:null;
$valor4 = isset($array4[$key])?$array4[$valor_total]:null;
}
}

echo mysql_error();

Felipe,

Ainda sou bem iniciante seria uma boa puxar do xml...mas é bem mais complicado do que fazer a entrada e saida manualmente no banco..

depois vou trocar para mysqli ou PDO...mas aprendendo uma coisa por vez senão a cabeça funde..kkk
Jayme A. C. Gimenez
Re: foreach gravando varias vezes no BD
13 de April de 2017 às 05:03PM
Não tem nenhum problema ser "muito iniciante" (aliás, esse fórum aqui é, justamente, para iniciantes). Agora, "muito iniciante" assumir tarefas concretas acima de suas habilidades já é um sério problema. Cuidado com isso.

Seu script ainda está bem compatível com "muito iniciante" rsrs. Mas também mostra que você está pesquisando e estudando. Não há outro caminho. Programar, mesmo que não seja em nível profissional, exige muuuuuuuito mais estudo e conhecimento que, por exemplo, fazer layouts em html.

Seu problema, agora, parece ser a dificuldade em entender o que são variáveis. Sem entender bem isso, é simplesmente impossível programar.

No trecho de script que lhe mostrei, $array1, $array2, etc, são apenas exemplos genéricos. No seu caso, $array1 teria que ser substituído por $_POST["cat_id"], $array2 por $_POST["qtd"], etc.

Depois de entender o conceito de variáveis, você vai precisar entender o que são os loops. O foreach é um loop. Seus inserts, por exemplo, teriam que estar dentro do loop foreach que lhe mostrei (e aqueles foreachs que você fez ali em cima não deveriam existir). A cada laço do loop, os dados são tirados pareados (aninhados) e, então, inseridos no banco de dados.

Por fim, pesquise melhor esse lance de last_insert_id . Veja se, do jeito que está fazendo, ele realmente funcionaria. Eu uso de uma forma diferente. Não sei dizer se a sua também funciona.
Roberto C
Re: foreach gravando varias vezes no BD
13 de April de 2017 às 08:16PM
Jayme,

Esse é projeto pessoal e não comercial por isso assumi comigo mesmo...rs..rs

Esse sistema vou usar de modo pessoal e to aproveitando para conhecer coisas novas e também gosto de mexer com isso...

Quanto ao last_insert_id consegui resolver da maneira abaixo: (não sei se é a correta mas funcionou..kkk)

mysql_query("INSERT INTO lc_controle (dia, mes, ano, dtConcat, clienteVa, clienteAt, userml, rastreador, entrega, total, frete, frete_real, nf, origem, tipo_pagto, descricao, tipo, tipo_venda) values
('$dia', '$mes', '$ano', '$dtConcat', '$clienteVa', '0', '$userml', '$rastreador', '$entrega', '$total', '$frete', '$frete_real', '$nf', '$origem', '$tipo_pagto', '$descricao','0','Varejo')");
mysql_query("SELECT LAST_INSERT_ID() INTO @ID");

mysql_query("INSERT INTO lc_detalhe (cat_id,qtd,valor_unid,valor_total,controle_id) values
('$cat_id','$qtd','$valor_unid','$valor_total',@ID)");

Agora só falta resolver esse problemão que grava varias vezes no BD..isso ta me deixando mais careca do que sou...rs..

Agradeço suas dicas e pode ter certeza que cada dica que vc da vou atrás para ler, conhecer e aprender.
Jayme A. C. Gimenez
Re: foreach gravando varias vezes no BD
13 de April de 2017 às 09:25PM
Adapte, para o seu sciprt, o foreach que lhe enviei, fazendo as substituições que citei, que seu "problemão" vai se resolver (se você também entender o conceito de loop e souber colocar suas queries de insert dentro dele).

Sobre o último id gravado no bd, eu uso o mysql_insert_id() . Logo depois (e fora dela, pois esse é um comando do PHP) da query de insert da qual você quer capturar o último id, você põe algo do tipo $ultimo_id = mysql_insert_id(); . E pronto: o id que você quer está na variável $ultimo_id e você pode usar na segunda query. Mas se funciona, também, do jeito que você fez, ótimo; o importante é funcionar!
Felipe M.
Re: foreach gravando varias vezes no BD
13 de April de 2017 às 10:17PM
Jayme A. C. Gimenez Escreveu:
-------------------------------------------------------
> Sobre o último id gravado no bd, eu uso o
> mysql_insert_id() .

> Mas se funciona, também, do jeito que você fez,
> ótimo; o importante é funcionar!

mysql_insert_id foi depreciado:
Aviso: Esta extensão está obsoleta desde o PHP 5.5.0 e foi removida no PHP 7.0.0.
http://php.net/manual/pt_BR/function.mysql-insert-id.php

Nesse caso, o importante não é só funcionar! É funcionar hoje e funcionar amanhã... Imagine ter de atualizar um GRANDE projeto com centenas de "mysql_insert_id". O PHP 7 já é a atualidade.

Vc (também) pode armazenar o último ID em uma variável com MAX():

mysql_query("INSERT INTO lc_controle (dia, mes, ano, dtConcat, clienteVa, clienteAt, userml, rastreador, entrega, total, frete, frete_real, nf, origem, tipo_pagto, descricao, tipo, tipo_venda) values
('$dia', '$mes', '$ano', '$dtConcat', '$clienteVa', '0', '$userml', '$rastreador', '$entrega', '$total', '$frete', '$frete_real', '$nf', '$origem', '$tipo_pagto', '$descricao','0','Varejo')");

$ultimo_id = mysql_query("SELECT MAX(`id`) FROM `lc_controle`;");

mysql_query("INSERT INTO lc_detalhe (cat_id,qtd,valor_unid,valor_total,controle_id) values
('$cat_id','$qtd','$valor_unid','$valor_total'," . $ultimo_id . ")");


PS: Ao utilizar o MAX(), vc realmente vai receber o "MAIOR" valor de `id`. O correto mesmo é utilizar o mysqli_insert_id() ou PDO::lastInsertId(), já que vai receber o "último ID inserido naquela conexão".
http://stackoverflow.com/questions/3180510/last-insert-id-vs-select-maxid
Jayme A. C. Gimenez
Re: foreach gravando varias vezes no BD
17 de April de 2017 às 09:01PM
No conteúdo, eu concordo com você, Felipe. Mas me permito fazer uma observação sobre a forma, o método que costumo usar aqui.

Aqui é um fórum para iniciantes. Assim, procuro tentar captar o que seria mais importante acrescentar, a quem pergunta aqui, em cada momento; porque não adianta dar uma montanha de informações de uma só vez para quem está começando...

Procuro ir passo a passo. No exemplo concreto, se o Roberto resolvesse usar a minha dica do mysql_insert_id() (que sequer é o principal problema dele, nesse post), e se ele conseguir resolver o problema principal, que é o ajuste do foreach, eu pretendia falar um pouco sobre o mysqli_insert_id() e o mysqli em geral.



Felipe M. Escreveu:
-------------------------------------------------------
> Jayme A. C. Gimenez Escreveu:
> --------------------------------------------------
> -----
> > Sobre o último id gravado no bd, eu uso o
> > mysql_insert_id() .
>
> > Mas se funciona, também, do jeito que você
> fez,
> > ótimo; o importante é funcionar!
>
> mysql_insert_id foi depreciado:
> Aviso: Esta extensão está obsoleta desde o PHP
> 5.5.0 e foi removida no PHP 7.0.0.
> http://php.net/manual/pt_BR/function.mysql-insert-
> id.php
>
> Nesse caso, o importante não é só funcionar! É
> funcionar hoje e funcionar amanhã... Imagine ter
> de atualizar um GRANDE projeto com centenas de
> "mysql_insert_id". O PHP 7 já é a atualidade.
>
> Vc (também) pode armazenar o último ID em uma
> variável com MAX():
>
> mysql_query("INSERT INTO lc_controle (dia, mes,
> ano, dtConcat, clienteVa, clienteAt, userml,
> rastreador, entrega, total, frete, frete_real, nf,
> origem, tipo_pagto, descricao, tipo, tipo_venda)
> values
> ('$dia', '$mes', '$ano', '$dtConcat',
> '$clienteVa', '0', '$userml', '$rastreador',
> '$entrega', '$total', '$frete', '$frete_real',
> '$nf', '$origem', '$tipo_pagto',
> '$descricao','0','Varejo')");
>
> $ultimo_id = mysql_query("SELECT MAX(`id`) FROM
> `lc_controle`;");
>
> mysql_query("INSERT INTO lc_detalhe
> (cat_id,qtd,valor_unid,valor_total,controle_id)
> values
> ('$cat_id','$qtd','$valor_unid','$valor_total'," .
> $ultimo_id . ")");
>
>
> PS: Ao utilizar o MAX(), vc realmente vai receber
> o "MAIOR" valor de `id`. O correto mesmo é
> utilizar o mysqli_insert_id() ou
> PDO::lastInsertId(), já que vai receber o
> "último ID inserido naquela conexão".
> http://stackoverflow.com/questions/3180510/last-in
> sert-id-vs-select-maxid
Roberto C
Re: foreach gravando varias vezes no BD
25 de April de 2017 às 05:34PM
Jayme boa tarde, consegui resolver a gravação das linhas...com suas dicas fui atras li, reli, fiz, refiz, mas agora deu certo.

Muito Obrigado pela ajuda e vamos aprendendo.

Agora empaquei em outra situação..kkk
Você precisa estar logado no PHPBrasil.com para poder enviar mensagens para os nossos fóruns.

Faça o login aqui.