Skip to content

Instantly share code, notes, and snippets.

@neoascetic
Last active August 1, 2016 13:04

Revisions

  1. neoascetic revised this gist Sep 5, 2013. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions nestedtransactor.php
    Original file line number Diff line number Diff line change
    @@ -25,7 +25,7 @@ protected static function get_pdo() {
    }

    protected static function nestable() {
    $current_driver = static::get_pdo()->getAttribute(PDO::ATTR_DRIVER_NAME);
    $current_driver = static::get_pdo()->getAttribute(\PDO::ATTR_DRIVER_NAME);
    return in_array($current_driver, static::$supported_drivers);
    }

    @@ -62,7 +62,7 @@ public static function transaction($callback) {
    static::begin_transaction();
    try {
    call_user_func($callback);
    } catch (Exception $e) {
    } catch (\Exception $e) {
    static::rollback_transaction();
    throw $e;
    }
  2. neoascetic revised this gist Mar 30, 2013. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion nestedtransactor.php
    Original file line number Diff line number Diff line change
    @@ -10,7 +10,7 @@
    *
    * To use this, you need to replace value under "DB" key in `application.aliases` config
    * with this class name. After this, you can continue to use Laravel-style transactions
    * (`DB::transaction`), but you need to relace all "raw PDO" transaction calls
    * (`DB::transaction`), but you need to replace all "raw PDO" transaction calls
    * (such as `DB::connection()->pdo->beginTransaction()`) with alternatives provided
    * by this class.
    */
  3. neoascetic created this gist Mar 29, 2013.
    72 changes: 72 additions & 0 deletions nestedtransactor.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,72 @@
    <?php

    /**
    * Class for Laravel 3.x that provides ability to use nested transactions via SAVEPOINTs
    * (inspired from http://www.kennynet.co.uk/2008/12/02/php-pdo-nested-transactions/).
    * For now, only the default connection is supported.
    *
    * Useful in testing, when you want to start a transaction before running a test
    * and revert all its changes after it finished.
    *
    * To use this, you need to replace value under "DB" key in `application.aliases` config
    * with this class name. After this, you can continue to use Laravel-style transactions
    * (`DB::transaction`), but you need to relace all "raw PDO" transaction calls
    * (such as `DB::connection()->pdo->beginTransaction()`) with alternatives provided
    * by this class.
    */

    class NestedTransactor extends \Laravel\Database {

    protected static $supported_drivers = ['pgsql', 'mysql', 'mysqli', 'sqlite'];
    protected static $transaction_level = 0;

    protected static function get_pdo() {
    return static::connection()->pdo;
    }

    protected static function nestable() {
    $current_driver = static::get_pdo()->getAttribute(PDO::ATTR_DRIVER_NAME);
    return in_array($current_driver, static::$supported_drivers);
    }

    protected static function process_pdo($pdo_method, $sql) {
    $pdo = static::get_pdo();
    if (static::$transaction_level == 0 || !static::nestable()) {
    $pdo->{$pdo_method}();
    } else {
    $pdo->exec($sql);
    }
    }

    public static function begin_transaction() {
    static::process_pdo('beginTransaction', 'SAVEPOINT LEVEL'.static::$transaction_level);
    static::$transaction_level++;
    }

    public static function commit_transaction() {
    static::$transaction_level--;
    static::process_pdo('commit', 'RELEASE SAVEPOINT LEVEL'.static::$transaction_level);
    }

    public static function rollback_transaction() {
    static::$transaction_level--;
    static::process_pdo('rollBack', 'ROLLBACK TO SAVEPOINT LEVEL'.static::$transaction_level);
    }

    /**
    * Redefined transaction method of Laravel\Database\Connection
    * @param callback $callback
    * @return void
    */
    public static function transaction($callback) {
    static::begin_transaction();
    try {
    call_user_func($callback);
    } catch (Exception $e) {
    static::rollback_transaction();
    throw $e;
    }
    return static::commit_transaction();
    }

    }