Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

JorgitoDF

Transações PDO em PHP

Recommended Posts

Boa noite pessoal, sou iniciante em PDO em PHP e estou com uma dificuldade em transações, gostaria de saber se alguém pode me ajudar neste ponto abaixo:

 

Quero colocar vários INSERT num único bloco de transação pois caso ocorra algum erro na gravação de alguma tabela todos os INSERT devem ser cancelados (rollback).

 

 

Segue o meu código:

<?php 
header("Content-Type: text/html; charset=UTF-8",true);
include("bd/conexao_pdo.php");

	$banco = conectar();

	$txtUf = $_POST['idUf'];
	$txtCidade = mb_strtoupper($_POST['idCidade']);
	$txtBairro = mb_strtoupper($_POST['idBairro']);


	$sql = 'INSERT INTO tb_cidade (cid_nome, fk_id_uf_tb_cidade) VALUES (:cidade, :fk_uf)';
	$sql1 = 'INSERT INTO tb_bairro (bai_nome, fk_id_cidade_tb_bairro) VALUES (:bairro, :fk_cidade)';



	$banco->beginTransaction();

	$create_cid = $banco->prepare($sql);
	$create_cid->bindValue(':cidade', $txtCidade, PDO::PARAM_STR);
	$create_cid->bindValue(':fk_uf', $txtUf, PDO::PARAM_INT);
	$create_cidade = $create_cid->execute();

	if (!$create_cidade) {
		$banco->rollBack();
   		die("Erro ao gravar Cidade");
	} else {
		$idCidade = $banco->lastInsertId();
		$banco->commit();
	}


	$banco->beginTransaction();

	$create_bai = $banco->prepare($sql1);
	$create_bai->bindValue(':bairro', $txtBairro, PDO::PARAM_STR);
	$create_bai->bindValue(':fk_cidade', $idCidade, PDO::PARAM_INT);
	$create_bairro = $create_bai->execute();

	if (!$create_bairro) {
		$banco->rollBack();
		die("Erro ao gravar Bairro");
	} else {
		$idBairro = $banco->lastInsertId();
		$banco->commit();
		echo "Dados gravados com sucesso...";
	}

?>

Compartilhar este post


Link para o post
Compartilhar em outros sites

Se você quiser que todos os inserts sejam revertidos em caso de erro, utilize apenas uma transaction e exceptions para tratar os erros dos inserts.

try {
    $banco->setAttribute(PDO::ATTR_ERRMODE , PDO::ERRMODE_EXCEPTION);//Ativa o lançamento de exceptions para erros
    $banco->beginTransaction();

    $create_cid = $banco->prepare($sql);
    $create_cid->bindValue(':cidade', $txtCidade, PDO::PARAM_STR);
    $create_cid->bindValue(':fk_uf', $txtUf, PDO::PARAM_INT);
    $create_cid->execute();//Não há necessidade em verificar o retorno, se não inserir, será lançada uma exception

    $create_bai = $banco->prepare($sql1);
    $create_bai->bindValue(':bairro', $txtBairro, PDO::PARAM_STR);
    $create_bai->bindValue(':fk_cidade', $idCidade, PDO::PARAM_INT);
    $create_bai->execute();//Não há necessidade em verificar o retorno, se não inserir, será lançada uma exception

    $banco->commit();
} catch (PDOException $exception) {
    $banco->rollback();

    printf('Não foi possível realizar a operação: %s' , $exception);
}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Em uma pesquisa no que fiz, no php 5.5 +

 

da para ver quais inserts falharam no bloco finally

try{

 //

} catch (PDOException $exception) {
    $banco->rollback();

    printf('Não foi possível realizar a operação: %s' , $exception);

} finally {

   // echo erro na sql tal

}

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não se esqueça de adicionar

 

$banco->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
ANTES de iniciar a transação

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não se esqueça de adicionar

 

$banco->setAttribute(PDO::ATTR_AUTOCOMMIT, false);
ANTES de iniciar a transação

 

Não há essa necessidade, beginTransaction automaticamente seta auto commit como false.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Há um porém em utilizar o bloco finally para tratar as sqls que deram errado, pois o finally é sempre executado, mesmo que nenhum erro aconteça. Logo, se é um tratamento específico de erros das queries, esse tratamento deve ser feito no catch.

Compartilhar este post


Link para o post
Compartilhar em outros sites

#6

Quem te ajudou foi o Gabriel Heming :grin:

 

 

 

Há um porém em utilizar o bloco finally para tratar as sqls que deram errado, pois o finally é sempre executado, mesmo que nenhum erro aconteça. Logo, se é um tratamento específico de erros das queries, esse tratamento deve ser feito no catch.

Sei!!! Mas era uma forma diferente, vi em um post em um fórum gringo, não me recordo a url, mas era uma forma diferente, pega o erro do catch e disparava um email dentro do finally, bem interessante, mas aqui para mim já não rola 5.4

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.