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:
- Inicie a transação chamando o
beginTransaction()
método do objeto PDO. - Coloque as instruções SQL e a
commit()
chamada do método em umtry
bloco. - No
catch
bloco, reverta a transação chamando orollBack()
método do objeto PDO.
Configurando uma tabela de exemplo
Criaremos uma tabela nomeada accounts
para demonstrar a transferência de dinheiro entre duas contas bancárias.
Primeiro, execute a seguinte instrução para criar a accounts
tabela:
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 accounts
tabela:
INSERT INTO accounts(name,amount)
VALUES('John',25000),
('Mary',95000);
Linguagem de código: SQL (linguagem de consulta estruturada) ( sql )
Terceiro, consulte a accounts
tabela:
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 catch
bloco) 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.