Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 虽然我喜欢这个词,但这个词很愚蠢_Php_Mysql_Zend Framework_Transactions_Pdo - Fatal编程技术网

Php 虽然我喜欢这个词,但这个词很愚蠢

Php 虽然我喜欢这个词,但这个词很愚蠢,php,mysql,zend-framework,transactions,pdo,Php,Mysql,Zend Framework,Transactions,Pdo,我有这样一种情况:我有可能被非我编写的模块调用的事件处理程序函数。我的事件处理程序在数据库中创建了很多记录。如果有什么东西没有正确通过,或是丢失了,或是有什么东西出了问题,那么我肯定需要回退。我不知道触发事件处理程序的外部模块的代码是否正在处理db事务,因为代码是由其他人编写的。我还没有找到查询数据库以查看事务是否正在进行的方法 所以我会数一数。我使用的是CodeIgniter,如果我要求它开始使用嵌套的db事务(例如多次调用它的trans_start()方法),它似乎会做一些奇怪的事情。换句话

我有这样一种情况:我有可能被非我编写的模块调用的事件处理程序函数。我的事件处理程序在数据库中创建了很多记录。如果有什么东西没有正确通过,或是丢失了,或是有什么东西出了问题,那么我肯定需要回退。我不知道触发事件处理程序的外部模块的代码是否正在处理db事务,因为代码是由其他人编写的。我还没有找到查询数据库以查看事务是否正在进行的方法

所以我会数一数。我使用的是CodeIgniter,如果我要求它开始使用嵌套的db事务(例如多次调用它的trans_start()方法),它似乎会做一些奇怪的事情。换句话说,我不能只在事件处理程序中包含trans_start(),因为如果外部函数也在使用trans_start(),则回滚和提交不会正确发生。总有一种可能,我还没有找到正确管理这些功能的方法,但我已经运行了许多测试

我的事件处理程序需要知道的是,另一个调用的模块是否已经启动了db事务?如果是这样,它不会启动另一个新事务,也不会执行任何回滚或提交。它确实相信,如果某个外部函数启动了db事务,那么它也将处理回滚/提交

我为CodeIgniter的事务方法提供了包装函数,这些函数递增/递减计数器

function transBegin(){
    //increment our number of levels
    $this->_transBegin += 1;
    //if we are only one level deep, we can create transaction
    if($this->_transBegin ==1) {
        $this->db->trans_begin();
    }
}

function transCommit(){
    if($this->_transBegin == 1) {
        //if we are only one level deep, we can commit transaction
        $this->db->trans_commit();
    }
    //decrement our number of levels
    $this->_transBegin -= 1;

}

function transRollback(){
    if($this->_transBegin == 1) {
        //if we are only one level deep, we can roll back transaction
        $this->db->trans_rollback();
    }
    //decrement our number of levels
    $this->_transBegin -= 1;
}

在我的情况下,这是检查现有db事务的唯一方法。它是有效的。我不会说“应用程序正在管理db事务”。在这种情况下,这是不真实的。它只是检查应用程序的某些其他部分是否启动了任何db事务,以便避免创建嵌套的db事务。

这个讨论相当古老。正如一些人所指出的,您可以在应用程序中实现这一点。PHP从版本5 > = 5.3.3有一个方法来知道您是否处于事务的中间。PDP::inTransaction()返回true或false。Link

也许您可以尝试PDO::inTransaction…如果事务当前处于活动状态,则返回TRUE,否则返回FALSE。
我还没有测试过自己,但似乎还不错

似乎那个问题在他们的追踪器里消失了…:(所有采埃孚问题均表示“在下一个次要版本中修复”我希望他们有充分的理由这样做,因为这会误导很多人,并给很多人带来困惑。在我通过mysql客户端进行的测试中,
SELECT@@autocommit;
在事务处理过程中仍然返回1。这的确是一个非常好的功能。我想知道它存在于Hibernate或任何类似的更成熟的持久性层中…Prope有这个,但我仍然认为它是一个伪造的设计。请参阅我上面的编辑。回到这个主题…例如JPA有TransactionManager的概念,对于ZF来说,类似的概念是合乎逻辑的吗?我不能对JPA说,但Java不是PHP,反之亦然。PHP假设请求建立了一个工作单元,因此PHP应用程序中事务的作用域应该与请求的作用域相同。这很简单。没有PHP应用程序服务器,因此没有“对话”事务的作用域。因此,不需要让域模型类或DAO类管理事务——只需在控制器级别执行即可。@Pacerier,我不知道什么是“bdbaft”意思是。也许框架的DB层没有封装这个检查事务状态的PDO方法。我和你的答案是一样的,在我看到你的答案之前,我几乎发布了我的答案。
wrapper.php:

try {
   // start transaction
   include("your_script.php");
   // commit transaction
} catch (RollbackException $e) {
   // roll back transaction
}
try {
    Zend_Registry::get('database')->beginTransaction();
} 
catch (Exception $e) { }

try {
    $totals = self::calculateTotals($Cart);

    $PaymentInstrument = new PaymentInstrument;
    $PaymentInstrument->create();
    $PaymentInstrument->validate();
    $PaymentInstrument->save();

    Zend_Registry::get('database')->commit();
    return true;
} 
catch (Zend_Exception $e) {
    Bootstrap::$Log->err($e->getMessage());
    Zend_Registry::get('database')->rollBack();
    return false;
}
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
function transBegin(){
    //increment our number of levels
    $this->_transBegin += 1;
    //if we are only one level deep, we can create transaction
    if($this->_transBegin ==1) {
        $this->db->trans_begin();
    }
}

function transCommit(){
    if($this->_transBegin == 1) {
        //if we are only one level deep, we can commit transaction
        $this->db->trans_commit();
    }
    //decrement our number of levels
    $this->_transBegin -= 1;

}

function transRollback(){
    if($this->_transBegin == 1) {
        //if we are only one level deep, we can roll back transaction
        $this->db->trans_rollback();
    }
    //decrement our number of levels
    $this->_transBegin -= 1;
}