跨越多个不同类的写方法的PHP PDO事务管理

时间:2016-09-07 15:01:03

标签: php pdo transactions

我需要帮助构建一种适当的方法来管理不同类上的多个数据访问方法的多个写入事务。

请考虑以下示例代码。

PDO连接类

class DBService {
    private static $instance = null;
    public static function connect() {
        if(self::$instance === null) {
            try {
                self::$instance = new PDO("mysql:host=myservername;dbname=mydbname", 'myusername', 'mypassword');
           } catch (\Exception $e) {
               return null;
           }
        }
        return self::$instance;
    }

    protected function __construct() {} // prevent creating new instance (faking a singleton)
}

数据库访问的订单存储库

class OrderRepository {
    public static function insert($data) {
        $con = DBService::connect();
        $stmt = $con->prepare('INSERT INTO Orders (customer_id, order_date) VALUES (:custId, NOW())');
        $stmt->execute(array(':custId'=>$data['custId']));
        return $con->lastInsertId();
    }
}

订单产品的OrderDetailRepository(lineitems)

class OrderDetailRepository {
    public static function insert($data) {
        $con = DBService::connect();
        $stmt = $con->prepare('INSERT INTO OrderDetails (order_id, product_id, quantity) VALUES (:orderId, :prodId, :qty)');
        $stmt->execute(array(':orderId'=>$data['orderId'],  ':prodId'=>$data['prodId'], ':qty'=>$data['qty']));
        return $con->lastInsertId();
    }
}

用于处理创建订单逻辑的服务类(即订单输入+订单详细信息条目)。这是我需要帮助理解如何实现事务的地方,这样如果第二个插入(订单详细信息)中出现错误,我可以回滚完成插入到Order表中的工作。

class OrderService {
    public static function createOrder($data) {
       try {
           $orderId = OrderRepository::insert($data);
           $orderDetailId = OrderDetailRepository::insert($data);

           // Commit transaction
       } catch (\Exception $e) {
           // Roll back transaction
           return false;
       }
       return true;
    }
}

我试图简化这个问题所以代码示例尽可能简约。但我仍然为冗长而道歉。

由于

1 个答案:

答案 0 :(得分:1)

简单地将事务包装在您控制活动流的位置,在本例中为OrderService->createOrder()方法

class OrderService {
    public static function createOrder($data) {
       try {
           $con = DBService::connect();
           $con->beginTransaction();

           $orderId = OrderRepository::insert($data);
           $orderDetailId = OrderDetailRepository::insert($data);

           // Commit transaction
           $con->commit();
       } catch (\Exception $e) {
           // Roll back transaction
           $con->rollback();
           return false;
       }
       return true;
    }
}

或者你可以将它移回一个级别并围绕调用OrderService->createOrder()

进行操作

然后可以将该方法简化为

class OrderService {
    public static function createOrder($data) {
       $orderId = OrderRepository::insert($data);
       $orderDetailId = OrderDetailRepository::insert($data);
    }
}

您的主要处理循环

try {
    $con = DBService::connect();
    $con->beginTransaction();

    $OrderService->createOrder($data);

    $con->commit();

} catch (\Exception $e) {
    // Roll back transaction
    $con->rollback();
}