Transação PHP MySQL

Resumo : neste tutorial, você aprenderá como lidar com transações MySQL em PHP para garantir a integridade dos dados do banco de dados.

Introdução à transação PHP MySQL

Uma transação é um conjunto de instruções SQL que precisam ser executadas do modo tudo ou nada.

Uma transação é considerada bem-sucedida somente se todas as instruções SQL forem executadas com sucesso. A falha de qualquer instrução fará com que o banco de dados volte ao estado original para evitar inconsistência de dados.

Um exemplo clássico de transação é uma transação de transferência de dinheiro de uma conta bancária para outra, envolvendo três etapas:

  • Primeiro, verifique o saldo do remetente para garantir que é suficiente para a transferência.
  • Em segundo lugar, se o valor for suficiente, deduza-o do saldo da conta do remetente.
  • Terceiro, adicione o valor ao saldo da conta do destinatário.

Se ocorrer um erro na segunda etapa, a terceira etapa não deverá prosseguir. Da mesma forma, se ocorrer um erro na terceira etapa, a segunda etapa deverá ser revertida.

Os valores de ambas as contas permanecem intactos em caso de falha ou são ajustados corretamente se a transação for concluída com sucesso.

Transação MySQL em PHP

Quando você usa o PDO para criar uma conexão com o banco de dados que suporta transações, o modo de confirmação automática é definido. Isso significa que cada consulta emitida é encapsulada em uma transação implícita.

Esteja ciente de que nem todos os mecanismos de armazenamento no MySQL suportam transações. Por exemplo, MyISAM não oferece suporte a transações, enquanto o InnoDB oferece.

Para lidar com transações MySQL em PHP, siga estas etapas:

  1. Inicie a transação chamando o beginTransaction()método do objeto PDO.
  2. Coloque as instruções SQL e a  commit()chamada do método em um trybloco.
  3. No catchbloco, reverta a transação chamando o rollBack()método do objeto PDO.

Configurando uma tabela de exemplo

Criaremos uma tabela nomeada accountspara demonstrar a transferência de dinheiro entre duas contas bancárias.

Primeiro, execute a seguinte instrução para criar a accountstabela:

CREATE TABLE accounts (
    id     INT AUTO_INCREMENT PRIMARY KEY,
    name   VARCHAR (50)    NOT NULL,
    amount DECIMAL (19, 4) NOT NULL
);Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Segundo, insira duas linhas na accountstabela:

INSERT INTO accounts(name,amount)
VALUES('John',25000),
      ('Mary',95000);Linguagem de código:  SQL (linguagem de consulta estruturada)  ( sql )

Terceiro, consulte a accountstabela:

SELECT * FROM accounts;Linguagem de código:  PHP  ( php )

Saída:

+----+------+------------+
| id | name | amount     |
+----+------+------------+
|  1 | John | 25000.0000 |
|  2 | Mary | 95000.0000 |
+----+------+------------+
2 rows in set (0.00 sec)Linguagem de código:  JavaScript  ( javascript )

Tratamento de transações em PHP

O script a seguir ilustra como lidar com transações em PHP:

<?php
require_once 'config.php';

function transfer($conn, $sender, $receiver, $amount)
{
    try {
        $conn->beginTransaction();

        // get balance of the sender
        $sql = 'SELECT amount FROM accounts WHERE id=:sender';
        $stmt = $conn->prepare($sql);
        $stmt->execute([":sender" => $sender]);
        $availableAmount = $stmt->fetchColumn();
        $stmt->closeCursor();

        if ($availableAmount < $amount) {
            echo 'Insufficient amount to transfer';
            return $conn->rollBack();
        }

        // deduct from the sender
        $sql_deduct = 'UPDATE accounts
		               SET amount = amount - :amount
				       WHERE id = :sender';

        $stmt = $conn->prepare($sql_deduct);
        $stmt->execute([":sender" => $sender, ":amount" => $amount]);
        $stmt->closeCursor();

        // add amount to the receiver
        $sql_add = 'UPDATE accounts
                    SET amount = amount + :amount
                    WHERE id = :receiver';

        $stmt = $conn->prepare($sql_add);
        $stmt->execute([":receiver" => $receiver, ":amount" => $amount]);

        // commit the transaction
        $conn->commit();
        echo 'The amount has been transferred successfully';
    } catch (PDOException $e) {
        if($conn) {
            $conn->rollBack();
        }
        die($e);
    }
}

// connect the database
$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);

// transfer 30K from from account 1 to 2
transfer($conn, 1, 2, 30000); // failed

// transfer 5K from from account 1 to 2
transfer($conn, 1, 2, 5000); // success
Linguagem de código:  PHP  ( php )

Como funciona.

Primeiro, defina uma função transfer() que transfere uma quantia do remetente para o destinatário.

Segundo, inicie uma nova transação chamando o método BeginTransaction():

$conn->beginTransaction();Linguagem de código:  PHP  ( php )

Terceiro, obtenha o saldo do remetente:

// get balance of the sender
$sql = 'SELECT amount FROM accounts WHERE id=:sender';
$stmt = $conn->prepare($sql);
$stmt->execute([":sender" => $sender]);
$availableAmount = $stmt->fetchColumn();
$stmt->closeCursor();Linguagem de código:  PHP  ( php )

Quarto, emita um erro se o valor disponível for menor que o valor que será transferido:

if ($availableAmount < $amount) {
    echo 'Insufficient amount to transfer';
    return $conn->rollBack();
}Linguagem de código:  PHP  ( php )

Quinto, deduza do saldo do remetente:

$sql_deduct = 'UPDATE accounts
               SET amount = amount - :amount
	       WHERE id = :sender';

$stmt = $conn->prepare($sql_deduct);
$stmt->execute([":sender" => $sender, ":amount" => $amount]);
$stmt->closeCursor();Linguagem de código:  PHP  ( php )

Sexto, adicione o valor ao saldo do destinatário:

$sql_add = 'UPDATE accounts
            SET amount = amount + :amount
            WHERE id = :receiver';

$stmt = $conn->prepare($sql_add);
$stmt->execute([":receiver" => $receiver, ":amount" => $amount]);Linguagem de código:  PHP  ( php )

Sétimo, confirme a transação chamando o método commit():

$conn->commit();Linguagem de código:  PHP  ( php )

Oitavo, reverta a transação (no catchbloco) se ocorrer algum erro:

$conn->rollBack();Linguagem de código:  PHP  ( php )

Teste

Primeiro, conecte-se ao banco de dados:

$conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);Linguagem de código:  PHP  ( php )

Segundo, transfira 30 mil da conta 1 para a conta 2:

$obj->transfer(1, 2, 30000);Linguagem de código:  PHP  ( php )

Erro:

Insufficient amount to transfer

Terceiro, faça outra transferência que transfira 5K da conta 1 para a conta 2:

$obj->transfer(1, 2, 5000);Linguagem de código:  PHP  ( php )

Saída:

The amount has been transferred successfully.

Neste tutorial, você aprendeu como gerenciar transações MySQL em PHP para garantir a integridade dos dados.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *