包装使用事务的类方法

时间:2016-02-19 15:08:21

标签: php mysql pdo transactions

我有多个类方法,如果抛出异常,每个方法都使用事务和回滚。以下基本示例。

class TaskMapper
{
    private $dblayer;

    public function __construct(PDO $dblayer)
    {
        $this->dblayer = $dblayer;
    }

    public function save(Task $task)
    {
        try {
            $this->dblayer->beginTransaction();

            $stmt = ... // query/queries here
            $stmt->execute();

            $stmt2 = ... // query/queries here
            $stmt2->execute();

            $this->dblayer->commit();

        } catch (\PDOException $e) {

            $this->dblayer->rollBack();
            // deal with exception here
        }


    }

    public function editField($id, $field, $value)
    {
        try {
            $this->dblayer->beginTransaction();

            $stmt = ... // query/queries here
            $stmt->execute();

            $stmt2 = ... // query/queries here
            $stmt2->execute();

            $stmt->execute();

            $this->dblayer->commit();

        } catch (\PDOException $e) {

            $this->dblayer->rollBack();
            // deal with exception here
        }
    }

}

现在,我正在编写一个cron作业的脚本,该脚本使用包含类似于上述代码的多个类方法 - 包括事务和回滚以及异常。

例如:

if (date('j') == '1') {
    // reset monthly count column
    $task->editField(17, 'monthly_count', '0');
}
$task->save($task);

这是一个非常剥离的示例,但我想知道是否可以在try / catch块中的单个事务中包装所有方法调用,并在catch中回滚?所以将上面的代码包装在try / catch中,并在catch中使用事务和回滚?

如果没有,那么接近这种情况的最佳方法是什么,如果一个方法调用失败,其他方法必须回滚。

提前致谢。

2 个答案:

答案 0 :(得分:1)

我宁愿添加一个答案,因为评论太短,无法解释。

基本上,您有两种方法可以在应用程序的单个事务中包含多个操作。

  1. 调用启动事务的方法。每个后续方法调用,属性更改都会导致数据库发生更改。这些操作期间的任何错误都将导致回滚。最后,您调用另一个提交整个事务的方法。

  2. 每个方法调用,属性更改只更改php对象状态,因此数据库不会更改。在对所有更改感到满意后,您将调用一个方法,该方法将所有更改持续存储到数据库中。此调用中也会执行回滚/提交。

  3. Mysql不支持嵌套事务,因此要么将第一个方法与PDO:inTransaction结合使用,因为@YourCommonSense也是在调用editField()之前启动事务建议的,或者你必须取出数据库修改代码来自editField()和类似的调用,只使用save()。

答案 1 :(得分:0)

我自己从未使用它,但有一个PDO::inTransaction方法,您可以使用它来查看是否启动了更高级别的事务。

所以你可以改为

if ( !$this->dblayer->inTransaction() ) {
    $this->dblayer->beginTransaction();
}

也适用于提交。

将让您决定是否必须使用“本地”事务,从而可以使用“全局”事务将所有这些方法包装在一起。