Um pouco do que gosto, faço e crio
Cakephp – Inserindo mais de um registro no banco de dados
Hoje me deparei com um probleminha ao precisar inserir mais de um registro no banco de uma vez.
A solução que eu procurava era para ter o seguinte efeito:
INSERT INTO tabela (titulo,created) VALUES ('11111', '2009-09-28 17:05:03');
INSERT INTO tabela (titulo,created) VALUES ('22222', '2009-09-28 17:05:03');
INSERT INTO tabela (titulo,created) VALUES ('33333', '2009-09-28 17:05:03');
INSERT INTO tabela (titulo,created) VALUES ('44444', '2009-09-28 17:05:03');
INSERT INTO tabela (titulo,created) VALUES ('55555', '2009-09-28 17:05:03');
Ou seja, eu precisava inserir uma série de registros de uma vez, sendo que no cakephp, se você escrever $this->Model->save($this->data) para um array com todos os campos, ele salva somente o ultimo registro, resultando em uma única inserção.
Para se ter sucesso nesta situação, seu array deve estar configurado conforme abaixo:
Não precisa estar configurado necessariamente assim, mas a meu ver, é a mais adequada.
array(
[Model] => array(
[0] => array(
[titulo] => '111111'
[texto] => 'xxxxxxx'
)
[2] => array(
[titulo] => '222222'
[texto] => 'xxxxxxx'
)
[3] => array(
[titulo] => '333333'
[texto] => 'xxxxxxx'
)
)
)
Em seu controller, você vai seguir a seguinte lógica:
foreach($this->data['Model'] as $item){
$this->Model->save($item);
$this->Model->id = null;
}
Explicando:
Linha 1: Passamos um foreach no array $this->data['Model']. Usamos este array para cair direto no array útil para este recurso que é o array Model.
Linha 2: Executamos o SAVE no model, normalmente. A diferença é que estaremos pegando o resultado do foreach, ou seja, estaremos pegando um bloco por vez do array e salvando.
Linha 3: É aqui que resolvemos o problema. Ao fim de cada inserção, devemos anular o ID. Se você não anular este ID, o Cakephp irá salvar somente o último insert, isso porque ele vai atribuindo o ID constantemente e no final, ele pega somente o id que está na variavel que é o último.
Essa dica não é daquelas que se acha facilmente na documentação do Cakephp, tão pouco no google, então, está aí a dica. Qualquer dúvida ou outras soluções, pode postar aqui.
Atualização: 29/09/09
Segue a dica do Richard, que é usar o mesmo array mostrado nest post e no save, colocar $this->Model->saveAll($data). Isso já resolve o problema e dispensa o uso do foreach.
Consulte o manual: http://book.cakephp.org/pt/view/75/Saving-Your-Data
Popularity: 21%
29/09/2009 - 09:31
If you are doing multiple inserts with Cake, you should call
$this->Model->create()before each save, or use$this->Model->saveAll($data);http://book.cakephp.org/view/75/Saving-Your-Data
29/09/2009 - 10:21
Obrigado pela dica Richard. Atualizei o artigo com sua dica.
Thanks for the tip Richard. I updated the article with your tip.
05/11/2009 - 20:07
Estou procurando como pegar o último ID inserido pelo save(). Ainda não encontrei, mas esse seu post vai ser muito útil, pois a próxima dúvida era exatamente essa. Vou testar amanhã pra ver se consigo. No meu caso é para um Banco de currículos, acho q vai servir pra cadastrar as X experiências, X formações, X idiomas, etc…..
valeu por enquanto e parabéns pelo post.
06/11/2009 - 07:40
Daniel, pra pegar o post mais recente vc pode fazer o seguinte:
$options = array(
‘order’=>array(
‘Model.id’=>’desc’
),
‘limit’=>1
);
$this->Model->find(‘first’,$options);
Dessa forma você ordena de baxo pra cima e limitando para um, pega o post mais recente.
[]’s
09/11/2009 - 16:31
Opa, Valeu Renan, vai me ser útil isso com certeza. Só nesse caso que eu precisava, acabei encontrando outra forma. Para deixar aqui para o pessoal, é seguinte; Como comentei tenho vários formulários na mesma tela, que cada um corresponde a uma tabela no bd, o que fiz é deixar os campos dos formularios com nomes corretos, e na hora de gravar ao invés de save(), dei um saveAll(). Pronto isso foi o suficiente, para ele gravar os dados, retornar o id e inserir tudo corretamente, SOZINHO! não precisei sequer retornar id. Show!
Segue um campo de exemplo:
MVC = Candidato
Campo =
MVC = Formacao
Campo =
E na hora de salvar:
$this->Candidato->saveAll($this->data, array(‘validate’=>’first’))
Pronto! Ele grava o candidato e já grava os relacionamentos sozinho, e o validate garante a validação de todos os campos de acordo com o que foi definido nos models de cada tabela. Claro que os campos das tabelas devem estar de acordo com o padrão do cake para relacionamentos.
25/02/2010 - 10:02
E ae cara, se você usar saveAll poderá inserir os registros no banco de dados todos de uma vez.