交易疑难解答

时间:2014-07-08 21:13:31

标签: php pdo transactions

我通过JavaScript从前端表单收集数据并将其传递给我的PHP脚本以保存到数据库。有三个表必须全部填充,或者没有(有错误)。我有以下文本墙作为我当前的脚本(为了便于阅读而大大缩写),我认为它可以工作,但我知道不会 - 列名错误拼写,应该抛出错误,但没有,并保存了另外两张表。

有谁可以指出我哪里出错?

    //SAVE TO DB
    $conn -> beginTransaction();
    $errors = array();


    //record edit
    foreach($edits as $edit)
    {
        try
        {
            $q = $conn  -> prepare(" INSERT INTO edits ( col1, col2 ) VALUES ( ?,? ) ");
            $q          -> execute( array( $a, $b ) );

        }
        catch(PDOException $e)
        {
            $conn->rollback();
            $errors['Edits'][] = $e->getMessage();
        }
    }

    //record action
    foreach($records as $id => $record)
    {
        if($haveExitingRecords)
        {
            //update existing record
            try
            {
                $q = $conn -> prepare(" UPDATE records SET col1 = ? WHERE ID = ? ");

                $q -> execute(array( $a, $b ));
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['Updates'][] = $e->getMessage();
            }
        }
        else
        {
            //insert new record
            try
            {
                $q = $conn -> prepare(" INSERT INTO records ( col1 ) VALUES ( ? ) ");

                $q -> execute( array( $a ) );
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['Inserts'][] = $e->getMessage();
            }
        }

        //also record where x...
        if($x !== 1)
        {
            try
            {
                //check for existing record
                $q = $conn  -> prepare(" SELECT ID FROM ifCases WHERE col1 = ? ");
                $q          -> execute( array( $a ) );
                $prev = $q  -> fetch(PDO::FETCH_COLUMN);

                if(!$prev)
                {
                    $q = $conn  -> prepare(" INSERT INTO ifCases ( col1, col2 ) VALUES ( ?, ? ) ");
                    $q          -> execute( array( $a, $b ) );
                }
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['ifCases'][] = $e->getMessage();
            }
        }
        else
        {
            try
            {
                //check for existing record
                $q = $conn  -> prepare(" SELECT ID FROM ifCases WHERE col1 = ? AND col2 = ? ");
                $q          -> execute(array( $a, $b ));
                $prev = $q  -> fetch(PDO::FETCH_COLUMN);

                if($prev > 0)
                {
                    try
                    {
                        //delete case
                        $q = $conn  -> prepare(" DELETE FROM ifCases WHERE  col1 = ? AND col2 = ? ");
                        $q          -> execute(array($ $a, $b ));
                    }
                    catch(PDOException $e)
                    {
                        $conn->rollback();
                        $errors['Delete ifCase'][] = $e->getMessage();
                    }
                }
            }
            catch(PDOException $e)
            {
                $conn->rollback();
                $errors['ifCases'][] = $e->getMessage();
            }
        }
    }

    if(empty($errors))
    {
        $conn->commit();
        echo '{"success":"ok"}';
    }
    else
    {
        echo json_encode($errors);
    }

1 个答案:

答案 0 :(得分:0)

所以你捕获一个异常,回滚事务,到目前为止完成的任何工作都没有完成。

但仅仅因为您回滚,并不意味着您的脚本无法执行后续语句。他们只是隐式地启动他们自己的新事务,如果你将MySQL的autocommit变量置于默认状态,他们会自动提交。

您应该在捕获异常时将代码从当前函数更改为exitreturn。或者设置一个标志变量,如果设置了标志,则跳过后续的数据库操作。