PHP / PDO如何重用连接在类中启动以解决“没有活动事务”错误

时间:2014-03-28 18:00:24

标签: php pdo transactions

我有一个类封装PDO定义为该示例:

class db{
       private $conn=null;

       function __construct(){
          getConn();
       }

       function getConn(){
        $this->conn = new PDO("mysql:host=localhost;dbname=database", 'username', 'password'); 
       }

    }

我希望在不同的类实例之间重用相同的数据库连接,这样我就可以在复杂的操作中使用事务,例如:

function getDataFromAnotherTable(){
 $db = new dbClass;
 $data = execute('select * from table2');
 return $data;
}

//main code start here...
$db = new db; //here i will instantiate class defined above
$db->beginTrans();
$db->execute(insert into table1);

//here transaction still active
$data = getDataFromAnotherTable()

//now transaction has been closed by previous call!

$db->execute('insert into table1');

 //here i receive "There is no active transaction" error because transaction is closed inside
 // getDataFromAnotherTable()
 $db->endTransaction();

我希望改变我的课程:

       function __construct(){
         if(empty($this->conn){             
          getConn();
         }             
        }

因此,如果连接已存在,将重复使用,并且不会创建新连接。 我已经尝试过这种方法但是每个类的实例都获得了新的连接,所以我不能重复使用相同的连接来维护我在不同类和函数上的事务。

请记住,这只是一个简化的例子!我的情况确实比较复杂,所以我不能使用以下内容执行单个插入语句:

select x from table1 insert into table2

提前感谢您的支持!

2 个答案:

答案 0 :(得分:0)

你基本上有两个选择。

首先,如果您在整个地方都有OOP,则必须将PDO连接作为类属性传递。

// having no class at hand I am passing $db into function as well
function getDataFromAnotherTable($db){
 $data = $db->execute('select * from table2');
 return $data;
}
$db = new db; //here i will instantiate class defined above
$db->beginTransaction();
$db->execute(insert into table1);
$data = getDataFromAnotherTable($db);
$db->execute('insert into table1');
$db->commit();

其次,你主要使用旧的普通程序风格,然后单身人士将是最好的答案。您只需要更改 - > to ::并摆脱这个new dbClass;的东西:

function getDataFromAnotherTable(){
    return DB::query('select * from table2')->fetchAll();
}

DB::beginTransaction();
DB::prepare("insert into table1 VALUES(?,?)")->execute([1,2]);
$data = getDataFromAnotherTable()
DB::prepare("insert into table1 VALUES(?,?)")->execute([3,4]);
DB::commit();

答案 1 :(得分:0)

你可以让$ conn成为一个静态变量......

class myClass
{
    private $conn = NULL;

    function __construct()
    {
        static $nDB = false;

        if ($nDB === false)
        {
            echo "INIT DB\n";
            $nDB = true;
        }

        $this->conn = $nDB;
    }
}

class myOne
{
    private $oDB = NULL;

    function __construct()
    {
        $this->oDB = new myClass();
    }
}

class myTwo
{
    private $oDB = NULL;

    function __construct()
    {
        $this->oDB = new myClass();
    }

}

$f1 = new myOne();
$f2 = new myTwo();

应该只有一个

的回声
INIT DB

这是因为$ conn在所有加载的myClass版本之间共享。