ZetCode

PHP PDO::inTransaction Method

last modified April 19, 2025

The PDO::inTransaction method checks if a transaction is currently active. It returns true if a transaction is in progress, false otherwise.

Basic Definition

PDO::inTransaction is a method of the PDO class in PHP. It determines whether the database connection is in the middle of a transaction.

Syntax: public PDO::inTransaction(): bool. No parameters are required. Returns a boolean value indicating transaction status.

Basic inTransaction Check

This example shows the basic usage of PDO::inTransaction method.

in_transaction_basic.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    echo "Before transaction: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->beginTransaction();
    echo "During transaction: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->commit();
    echo "After transaction: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

This code checks transaction status before, during, and after a transaction. The output shows false before, true during, and false after the transaction.

Nested Transactions Check

This demonstrates how inTransaction behaves with nested transactions.

in_transaction_nested.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    echo "Level 0: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->beginTransaction();
    echo "Level 1: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->beginTransaction(); // This will throw an exception
    echo "Level 2: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->commit();
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage() . "\n";
    echo "Current status: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
}

This shows that PDO doesn't support true nested transactions. The second beginTransaction throws an exception. inTransaction still returns true.

inTransaction with Rollback

This example shows transaction status during a rollback operation.

in_transaction_rollback.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $pdo->beginTransaction();
    echo "After begin: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->exec("INSERT INTO test (name) VALUES ('Test')");
    
    $pdo->rollBack();
    echo "After rollback: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

The code starts a transaction, performs an insert, then rolls back. inTransaction returns true before rollback and false after it completes.

inTransaction in Error Handling

This shows how to use inTransaction in error handling scenarios.

in_transaction_error.php
<?php

declare(strict_types=1);

$pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

try {
    $pdo->beginTransaction();
    
    $pdo->exec("UPDATE accounts SET balance = balance - 100 WHERE user_id = 1");
    $pdo->exec("INVALID SQL STATEMENT"); // This will fail
    
    $pdo->commit();
} catch (PDOException $e) {
    echo "Error occurred: " . $e->getMessage() . "\n";
    echo "Still in transaction: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
        echo "Transaction rolled back\n";
    }
}

When an error occurs, inTransaction helps determine if rollback is needed. This prevents trying to rollback when no transaction is active.

inTransaction with Savepoints

This demonstrates transaction status when using savepoints.

in_transaction_savepoint.php
<?php

declare(strict_types=1);

try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $pdo->beginTransaction();
    echo "Main transaction: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->exec("SAVEPOINT point1");
    echo "After savepoint: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->exec("ROLLBACK TO SAVEPOINT point1");
    echo "After rollback to savepoint: " . ($pdo->inTransaction() ? 'Yes' : 'No') . "\n";
    
    $pdo->commit();
} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

Savepoints don't affect the overall transaction status. inTransaction returns true throughout the operation until commit or rollback.

inTransaction with Different Databases

This shows how inTransaction works with different database drivers.

in_transaction_drivers.php
<?php

declare(strict_types=1);

// MySQL example
try {
    $mysql = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $mysql->beginTransaction();
    echo "MySQL inTransaction: " . ($mysql->inTransaction() ? 'Yes' : 'No') . "\n";
    $mysql->commit();
} catch (PDOException $e) {
    echo "MySQL Error: " . $e->getMessage();
}

// SQLite example
try {
    $sqlite = new PDO('sqlite:test.db');
    $sqlite->beginTransaction();
    echo "SQLite inTransaction: " . ($sqlite->inTransaction() ? 'Yes' : 'No') . "\n";
    $sqlite->commit();
} catch (PDOException $e) {
    echo "SQLite Error: " . $e->getMessage();
}

The inTransaction method works consistently across different database drivers. Both MySQL and SQLite show the same behavior.

Practical Transaction Management

This shows a practical use of inTransaction in a database operation.

in_transaction_practical.php
<?php

declare(strict_types=1);

function transferFunds(PDO $pdo, int $from, int $to, float $amount): bool {
    if ($pdo->inTransaction()) {
        throw new RuntimeException("Already in transaction");
    }
    
    try {
        $pdo->beginTransaction();
        
        // Check sender balance
        $stmt = $pdo->prepare("SELECT balance FROM accounts WHERE id = ?");
        $stmt->execute([$from]);
        $balance = $stmt->fetchColumn();
        
        if ($balance < $amount) {
            throw new RuntimeException("Insufficient funds");
        }
        
        // Perform transfer
        $pdo->prepare("UPDATE accounts SET balance = balance - ? WHERE id = ?")
            ->execute([$amount, $from]);
        $pdo->prepare("UPDATE accounts SET balance = balance + ? WHERE id = ?")
            ->execute([$amount, $to]);
            
        $pdo->commit();
        return true;
    } catch (Exception $e) {
        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }
        error_log("Transfer failed: " . $e->getMessage());
        return false;
    }
}

// Usage
try {
    $pdo = new PDO('mysql:host=localhost;dbname=testdb', 'user', 'password');
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    $success = transferFunds($pdo, 1, 2, 100.00);
    echo "Transfer " . ($success ? "succeeded" : "failed") . "\n";
} catch (PDOException $e) {
    echo "Database error: " . $e->getMessage();
}

This practical example uses inTransaction to check for existing transactions before starting a new one. It also verifies transaction status before rollback.

Best Practices

Source

PHP PDO::inTransaction Documentation

This tutorial covered the PDO::inTransaction method with practical examples showing its usage in different scenarios.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all PHP PDO Functions.