diff --git a/README.md b/README.md index d7c72eb..9429117 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ Library on [Packagist](https://packagist.org/packages/usmanhalalit/pixie). - [Insert with ON DUPLICATE KEY statement](#insert-with-on-duplicate-key-statement) - [**Update**](#update) - [**Delete**](#delete) + - [Transactions](#transactions) - [Get Built Query](#get-built-query) - [Sub Queries and Nested Queries](#sub-queries-and-nested-queries) - [Get PDO Instance](#get-pdo-instance) @@ -469,6 +470,45 @@ QB::table('my_table')->where('id', '>', 5)->delete(); ``` Will delete all the rows where id is greater than 5. +### Transactions + +Pixie has the ability to run database "transactions", in which all database +changes are not saved until committed. That way, if something goes wrong or +differently then you intend, the database changes are not saved and no changes +are made. + +Here's a basic transaction: + +```PHP +QB::transaction(function ($qb) { + $qb->table('my_table')->insert(array( + 'name' => 'Test', + 'url' => 'example.com' + )); + + $qb->table('my_table')->insert(array( + 'name' => 'Test2', + 'url' => 'example.com' + )); +}); +``` + +If this were to cause any errors (such as a duplicate name or some other such +error), neither data set would show up in the database. If not, the changes would +be successfully saved. + +If you wish to manually commit or rollback your changes, you can use the +`commit()` and `rollback()` methods accordingly: + +```PHP +QB::transaction(function (qb) { + $qb->table('my_table')->insert(array(/* data... */)); + + $qb->commit(); // to commit the changes (data would be saved) + $qb->rollback(); // to rollback the changes (data would be rejected) +}); +``` + ### Get Built Query Sometimes you may need to get the query string, its possible. ```PHP diff --git a/src/Pixie/QueryBuilder/QueryBuilderHandler.php b/src/Pixie/QueryBuilder/QueryBuilderHandler.php index 7f89796..0c508f6 100644 --- a/src/Pixie/QueryBuilder/QueryBuilderHandler.php +++ b/src/Pixie/QueryBuilder/QueryBuilderHandler.php @@ -789,18 +789,37 @@ public function join($table, $key, $operator = null, $value = null, $type = 'inn return $this; } + /** + * Runs a transaction + * + * @param $callback + * + * @return $this + */ public function transaction(\Closure $callback) { try { + // Begin the PDO transaction $this->pdo->beginTransaction(); - $callback($this); + // Get the Transaction class + $transaction = $this->container->build('\\Pixie\\QueryBuilder\\Transaction', array($this->connection)); + + // Call closure + $callback($transaction); + + // If no errors have been thrown or the transaction wasn't completed within + // the closure, commit the changes $this->pdo->commit(); - return true; + return $this; + } catch (TransactionHaltException $e) { + // Commit or rollback behavior has been handled in the closure, so exit + return $this; } catch (\Exception $e) { + // something happened, rollback changes $this->pdo->rollBack(); - return false; + return $this; } } diff --git a/src/Pixie/QueryBuilder/Transaction.php b/src/Pixie/QueryBuilder/Transaction.php new file mode 100644 index 0000000..bcad009 --- /dev/null +++ b/src/Pixie/QueryBuilder/Transaction.php @@ -0,0 +1,22 @@ +pdo->commit(); + throw new TransactionHaltException(); + } + + /** + * Rollback the database changes + */ + public function rollback() { + $this->pdo->rollBack(); + throw new TransactionHaltException(); + } +} diff --git a/src/Pixie/QueryBuilder/TransactionHaltException.php b/src/Pixie/QueryBuilder/TransactionHaltException.php new file mode 100644 index 0000000..c4795fa --- /dev/null +++ b/src/Pixie/QueryBuilder/TransactionHaltException.php @@ -0,0 +1,5 @@ +