Как работать с транзакциями PDO [duplicate]

Чтобы использовать методы и член объекта, вам сначала нужно создать этот объект. Если вы его не создали (переменная, которая должна содержать объект, не инициализируется), но вы пытаетесь использовать его методы или переменные, вы получите эту ошибку.

Иногда вы можете просто забыть инициализировать .

Отредактировано: new не может вернуть значение null, но исключение огня при ошибке. Давно это было на некоторых языках, но не больше. Спасибо @John Saunders за указание на это.

7
задан TimWolla 23 December 2011 в 19:29
поделиться

3 ответа

Я бы не готовил & amp; выполнять транзакционные заявления. Я использовал бы PDO :: beginTransaction () , PDO :: commit () и PDO :: rollback () .

PDO :: prepare () и PDO :: execute () возвращают FALSE, если есть ошибка, иначе они генерируют исключение PDOException, если вы setAttribute (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION) .

В вашем обработчике исключений вы должны проверить PDO :: errorInfo () и сообщить о характере ошибки. Лучше всего регистрировать необработанную информацию об ошибке, но дать пользователю более дружественное сообщение.

Не эхо-буквенное сообщение об ошибке в пользовательском интерфейсе - это может дать пользователю неуместные знания о вашем SQL-запросе и схема.

6
ответ дан Bill Karwin 26 August 2018 в 03:56
поделиться

Некоторые общие замечания: Не используйте bindParam(), если вы не используете процедуру, которая изменяет значение параметра. Поэтому use bindValue(). bindParam () принимает значение аргумента как ссылочную переменную. Это означает, что вы не можете сделать $stmt->bindParam(':num', 1, PDO::PARAM_INT); - это вызывает ошибку. Кроме того, PDO имеет свои собственные функции для управления транзакциями, вам не нужно выполнять запросы вручную.

Я немного переписал ваш код, чтобы пролить свет на то, как можно использовать PDO:

if($_POST['groupID'] && is_numeric($_POST['groupID']))
{
    // List the SQL strings that you want to use
    $sql['privileges']  = "DELETE FROM users_priveleges WHERE GroupID=:groupID";
    $sql['groups']      = "DELETE FROM groups WHERE GroupID=:groupID"; // You don't need LIMIT 1, GroupID should be unique (primary) so it's controlled by the DB
    $sql['users']       = "DELETE FROM users WHERE Group=:groupID";

    // Start the transaction. PDO turns autocommit mode off depending on the driver, you don't need to implicitly say you want it off
    $pdo->beginTransaction();

    try
    {
        // Prepare the statements
        foreach($sql as $stmt_name => &$sql_command)
        {
            $stmt[$stmt_name] = $pdo->prepare($sql_command);
        }

        // Delete the privileges
        $stmt['privileges']->bindValue(':groupID', $_POST['groupID'], PDO::PARAM_INT);
        $stmt['privileges']->execute();

        // Delete the group
        $stmt['groups']->bindValue(":groupID", $_POST['groupID'], PDO::PARAM_INT);
        $stmt['groups']->execute();

        // Delete the user 
        $stmt['users']->bindParam(":groupID", $_POST['groupID'], PDO::PARAM_INT);
        $stmt['users']->execute();

        $pdo->commit();     
    }
    catch(PDOException $e)
    {
        $pdo->rollBack();

        // Report errors
    }    
}
22
ответ дан N.B. 26 August 2018 в 03:56
поделиться

Задание PDO execute() возвращает TRUE при успешном завершении и FALSE при сбое, поэтому вы можете проверить возвращаемое значение предыдущего execute() в вашем операторе if.

$pdo_result = $dbs->execute();
if ($pdo_result) {
    // handle success
} else {
    // handle failure
    // you can get error info with $dbs->errorInfo();
}

Это говорит о том, что @ Билл Кервин правильно указывает (в своем ответе, что я полностью выдвигаю, потому что это точно правильно), было бы предпочтительнее использовать PDO::beginTransaction(), PDO::commit() и PDO::rollback().

3
ответ дан Trott 26 August 2018 в 03:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: