Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added transactions support #24

Merged
merged 1 commit into from
Sep 30, 2024
Merged

Conversation

ibnsultan
Copy link
Member

What kind of change does this PR introduce?

  • Feature
  • Bugfix
  • Code style update
  • Refactor
  • Build-related changes
  • Other, please describe below

Description

This PR introduces support for database transactions in the Leaf\Db class. The following methods have been added to handle transactions:

  • beginTransaction: Starts a database transaction.
  • commit: Commits the current transaction.
  • rollback: Rolls back the current transaction in case of an error.
  • transaction: A shorthand method that accepts a callback, wrapping it in a transaction. If the callback throws an exception, the transaction is rolled back; otherwise, it is committed.

These additions make database interaction safer by ensuring that a series of operations can be treated as a single unit, either all succeeding or all failing, improving consistency and error handling.

Does this PR introduce a breaking change?

  • Yes
  • No

Related Issue

No related issues were reported.

@ibnsultan ibnsultan added the enhancement New feature or request label Sep 30, 2024
@mychidarko
Copy link
Member

😂😂 the laziness didn't win

@mychidarko
Copy link
Member

Can you add an example usage in this chat, I'll update the documentation to add this feature

@ibnsultan
Copy link
Member Author

Can you add an example usage in this chat, I'll update the documentation to add this feature

Be back in a couple of minutes 😆

@ibnsultan
Copy link
Member Author

ibnsultan commented Sep 30, 2024

Database Transaction Examples

This document showcases various examples of database transactions.

Note: the shorthand for the transaction, does not necessary have to be wrapped in the try catch statement as it's already provided unless you need to have a more precise handling

Sample Schema Dump

Example 1: Delete a User within a Transaction

This example demonstrates how to delete a user within a transaction. If the deletion fails, the transaction will roll back.

try {
    db()->beginTransaction();
    db()->query("DELETE FROM users WHERE id = ?")->bind(1)->execute();
    db()->commit();
    
    echo "Transaction completed: User with ID 1 deleted.\n";
} catch (\Exception $e) {
    db()->rollback();
    echo "Transaction failed: Could not delete user with ID 1.\n";
}

Example 2: Simple Transaction Using Transaction Shorthand

This example shows how to perform a simple transaction using shorthand syntax.

db()->transaction(function() use ($userId) {
    db()->query("DELETE FROM users WHERE id = ?")->bind($userId)->execute();
});

echo "Transaction completed: User with ID {$userId} deleted using shorthand.\n";

Example 3: Insert an Order and Update Product Stock (Successful Transaction)

In this example, an order is inserted and the product stock is updated successfully.

db()->transaction(function() use ($userId, $productId, $quantity) {
    db()->query("UPDATE products SET stock = stock - ? WHERE id = ?")
        ->bind($quantity, $productId)
        ->execute();
    
    db()->query("INSERT INTO orders (user_id, product_id, quantity) VALUES (?, ?, ?)")
        ->bind($userId, $productId, $quantity)
        ->execute();
});

echo "Transaction completed: Order placed and stock updated.\n";

Example 4: Insufficient Stock, Transaction Rollback

This example checks for sufficient stock before proceeding with the transaction. If stock is insufficient, the transaction rolls back.

try {
    db()->transaction(function() use ($userId, $productId, $quantity) {
        $product = db()->query("SELECT stock FROM products WHERE id = ?")
            ->bind($productId)
            ->fetch();

        if ($product['stock'] < $quantity) {
            throw new Exception("Insufficient stock for product.");
        }

        db()->query("UPDATE products SET stock = stock - ? WHERE id = ?")
            ->bind($quantity, $productId)
            ->execute();

        db()->query("INSERT INTO orders (user_id, product_id, quantity) VALUES (?, ?, ?)")
            ->bind($userId, $productId, $quantity)
            ->execute();
    });

    echo "Transaction completed: Order placed and stock updated.\n";
} catch (\Exception $e) {
    echo "Transaction failed: {$e->getMessage()}.\n";
}

Example 5: Multiple Dependent Queries with Error Handling (Successful Transaction)

This example demonstrates multiple dependent queries with error handling.

db()->transaction(function() use ($userId, $amount) {
    db()->query("UPDATE users SET balance = balance - ? WHERE id = ?")
        ->bind($amount, $userId)
        ->execute();

    db()->query("INSERT INTO transaction_logs (user_id, amount, type) VALUES (?, ?, ?)")
        ->bind($userId, $amount, 'debit')
        ->execute();
});

Example 6: Inserting an Order Log and Failing During a Dependent Query

This example illustrates inserting an order log and handling failure during a dependent query.

try {
    db()->transaction(function() use ($orderId) {
        db()->query("INSERT INTO order_logs (order_id, status) VALUES (?, ?)")
            ->bind($orderId, 'processing')
            ->execute();

        // Simulate a failure during a dependent query
        throw new Exception("Failed to update order status.");

        db()->query("UPDATE orders SET status = ? WHERE id = ?")
            ->bind('processed', $orderId)
            ->execute();
    });

    echo "Transaction completed: Order log and status updated.\n";
} catch (\Exception $e) {
    echo "Transaction failed: {$e->getMessage()}.\n";
}

@ibnsultan ibnsultan merged commit 7a113d0 into leafsphp:next Sep 30, 2024
0 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants