php - 如何在 PDO 类中添加 MySQL 事务?

标签 php mysql pdo rollback autocommit

我创建了一个 PDO 类来帮助我与 MySQL 服务器连接和通信。 我正在尝试向类中添加一个函数或方法,以帮助我打开 MySQL 事务以及提交和回滚。我从来没有使用过提交和回滚。

我认为,场景会以某种方式在每次调用此类时停止自动提交,并在引发错误时回滚,并在每次此类 id 关闭时提交。

我的两个问题是: 1)打开连接然后运行多个查询提交(如果没有错误)是一个好主意,否则回滚然后关闭连接? 2)如何调用我设法将其添加到我现有的类(class)中? 这是我当前的 PHP 类(class)

<?php

class connection {

    private $connString;
    private $userName;
    private $passCode;
    private $server;
    private $pdo;
    private $errorMessage;
    private $pdo_opt = array();
    protected $lastQueryTime;
    protected $lastQuery;
    protected $effectedRows;



    function __construct($dbName = DATABASE_NAME, $serverName = DATABASE_HOST){

        //SET PDO options
        if(TESTING_ENVIRONMENT == 1){
            $this->pdo_opt[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
            $this->pdo_opt[PDO::ATTR_DEFAULT_FETCH_MODE]  = PDO::FETCH_ASSOC;
        }

            $this->pdo_opt[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES utf8';
            $this->pdo_opt[PDO::SQLSRV_ATTR_ENCODING]  = PDO::SQLSRV_ENCODING_UTF8;

        //sets credentials
        $this->setConnectionCredentials($dbName, $serverName);

        //start the connect
        $this->startConnection();

    }

    function startConnection(){


            $this->pdo = new PDO($this->connString, $this->userName, $this->passCode, $this->pdo_opt);

            if( ! $this->pdo){

                $this->errorMessage  = 'Failed to connect to database. Please try to refresh this page in 1 minute. ';
                $this->errorMessage .= 'However, if you continue to see this message please contact your system administrator.';
                echo $this->getError();
            }
    }


    //this will close the PDO connection
    public function endConnection(){

        $this->pdo = null;
    }

    //return a dataset with the results
    public function getDataSet($query, $data = NULL)
    {
        $start = microtime(true);
        $cmd = $this->pdo->prepare( $query );

        $cmd->execute($data);
        $this->effectedRows = $cmd->rowCount();
        $ret = $cmd->fetchAll();
        //$cmd->closeCursor();
        $this->lastQueryTime = microtime(true) - $start;
        $this->lastQuery = $query;

        return $ret;
    }



    public function processQuery($query, $data = NULL)
    {
        $start = microtime(true);
               //$this->pdo->beginTransaction();


        $cmd = $this->pdo->prepare( $query );
        $ret = $cmd->execute($data);
               //$this->pdo->commit();
               //$cmd->closeCursor();
        $this->effectedRows = $cmd->rowCount();
        $this->lastQueryTime = microtime(true) - $start;
        $this->lastQuery = $query;

        return $ret;
    }


    //return last insert id
    public function lastInsertId($name = NULL) {
        if(!$this->pdo) {
            return false;
        }

        return $this->pdo->lastInsertId($name);
    }


    //return last insert id
    public function rowCount() {

        return $this->effectedRows;
    }


    public function getOneResult($query, $data = NULL){
        $cmd = $this->pdo->prepare( $query );
        $cmd->execute($data);

        return $cmd->fetchColumn();
    }

    public function getError(){
        if($this->errorMessage != '')
            return $this->errorMessage;
        else
            return true;  //no errors found

    }

    //this where you need to set new server credentials with a new case statment
    function setConnectionCredentials($dbName, $serv){

        switch($serv){

            //the defaults are predefined in the APP_configuration file - DO NOT CHANGE THE DEFAULT
            default:
                $this->connString   = 'mysql:host='.DATABASE_HOST.';dbname='.DATABASE_NAME.';charset=utf8';
                $this->userName     = DATABASE_USERNAME;
                $this->passCode     = DATABASE_PASSWORD;
            break;

            }

    }

public function lastQueryTime() {
    if(!$this->lastQueryTime) {
        throw new Exception('no query has been executed yet');
    }
    return $this->lastQueryTime;
}

public function lastQuery() {
    if(!$this->lastQuery) {
        throw new Exception('no query has been executed yet');
    }
    return $this->lastQuery;
}

}

?>

已编辑 收集通知后我需要这样吗?

$db = new connection();
$db->beginTransaction(); //begin transaction
$db->processQuery();     //process query #1
$db->processQuery();     //process query #2
$db->commit();           //commit changes
$db->endConnection();    //close connection


public function beginTransaction(){
    $this->pdo->beginTransaction(); 
}

public function commit(){
    $this->pdo->commit(); 
}

public function rollBack(){
    $this->pdo->rollBack(); 
}   

//this will close the PDO connection
public function endConnection(){
    $this->pdo = null;
}

最佳答案

PDO::beginTransaction

/* Begin a transaction, turning off autocommit */
$dbh->beginTransaction();

PDO::commit

/* Commit the changes */
$dbh->commit();

此时,感觉您的 connection 类的级别相当低。我的猜测是它没有足够的信息来自行了解何时开始事务以及何时提交事务。您可能必须提供相应的方法(以及 rollback 方法),并让您的类的用户在需要时调用它们。

<小时/>

关于你的问题,事务不仅仅是回滚本地更改。也是关于atomicity 。这是一系列操作,要么全部完成,要么根本不完成。不要忘记将对您的数据库进行并发访问。有时,您不希望有人在您操作数据时更改数据。

关于php - 如何在 PDO 类中添加 MySQL 事务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18004715/

相关文章:

php - 在 WooCommerce 中更改购物车总价

mysql - MySQL 查询无结果

MySQL: 无法创建表 (errno: 150)

php - nd_pdo_mysql 和 pdo_mysql 扩展之间有什么区别?

php - PDOStatement->bindParam 不起作用

php - curl 给出错误 curl : (7) couldn't connect to host

javascript - PHP - GET url 忽略换行符

mysql - 使用 SQL 查询获取每天的第一次和最后一次时间

php - 如何将 MySQL 语句 'show index' 与 PDO 一起使用?

php - Zend 的可能缺点