Pregunta ¿Transacciones PHP PDO?


Tengo una página de registro y básicamente necesito datos insertados en 4 tablas. Soy nuevo en PDO y estoy confundido por algo.

Básicamente, si alguno de los insertos falla, no quiero agregar nada a la base de datos, eso parece bastante simple.

Mi confusión es que necesito insertar el nombre de usuario, el correo electrónico, la contraseña, etc. de los usuarios en mi users tabla para poder obtener (no estoy seguro cómo) utilizando PDO el uid que MySQL le ha dado a mi usuario (auto incrementado por mysql). Necesito el usuario uid MySQL le dio a mi usuario las otras tablas, ya que las otras tablas necesitan el uid para que todo esté vinculado correctamente. Mis tablas son InnoDB y tengo claves externas que van desde users_profiles (user_uid), users_status (user_uid), users_roles (user_uid) hasta users.user_uid para que estén todos vinculados entre sí.

Pero, al mismo tiempo, quiero asegurarme de que, por ejemplo, después de insertar los datos en el users tabla (para que pueda obtener el usuario MySQL dio usuario) que si cualquiera de las otras inserciones falla que elimina los datos que se insertaron en el users mesa.

Creo que es mejor que muestre mi código; He comentado el código y lo he explicado en el código, lo que puede facilitar su comprensión.

// Begin our transaction, we need to insert data into 4 tables:
// users, users_status, users_roles, users_profiles
// connect to database
$dbh = sql_con();

// begin transaction
$dbh->beginTransaction();

try {

    // this query inserts data into the `users` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users`
                        (users_status, user_login, user_pass, user_email, user_registered)
                        VALUES
                        (?, ?, ?, ?, NOW())');

    $stmt->bindParam(1, $userstatus,     PDO::PARAM_STR);
    $stmt->bindParam(2, $username,       PDO::PARAM_STR);
    $stmt->bindParam(3, $HashedPassword, PDO::PARAM_STR);
    $stmt->bindParam(4, $email,          PDO::PARAM_STR);
    $stmt->execute();

    // get user_uid from insert for use in other tables below
    $lastInsertID = $dbh->lastInsertId();

    // this query inserts data into the `users_status` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users_status`
                        (user_uid, user_activation_key)
                        VALUES
                        (?, ?)');

    $stmt->bindParam(1, $lastInsertID,     PDO::PARAM_STR);
    $stmt->bindParam(2, $activationkey,    PDO::PARAM_STR);
    $stmt->execute();

    // this query inserts data into the `users_roles` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users_roles`
                        (user_uid, user_role)
                        VALUES
                        (?, ?)');

    $stmt->bindParam(1, $lastInsertID,      PDO::PARAM_STR);
    $stmt->bindParam(2, SUBSCRIBER_ROLE,    PDO::PARAM_STR);
    $stmt->execute();

    // this query inserts data into the `users_profiles` table
    $stmt = $dbh->prepare('
                        INSERT INTO `users_profiles`
                        (user_uid)
                        VALUES
                        (?)');

    $stmt->bindParam(1, $lastInsertID,      PDO::PARAM_STR);
    $stmt->execute();

    // commit transaction
    $dbh->commit();

} // any errors from the above database queries will be catched
catch (PDOException $e) {
    // roll back transaction
    $dbh->rollback();
    // log any errors to file
    ExceptionErrorHandler($e);
    require_once($footer_inc);
    exit;
}

Soy nuevo en PDO y es posible que haya errores o problemas que todavía no he notado porque no puedo probarlos hasta que descubra mi problema.

1) Necesito saber cómo puedo insertar los datos de los usuarios en la tabla de usuarios primero para que pueda obtener el uid que MySQL le dio a mi usuario

2) Luego obtenga el uid como lo necesito para las otras tablas

3) Pero al mismo tiempo, si una consulta falla por cualquier motivo después de insertar en la tabla de usuarios, también se eliminan los datos de la tabla de usuarios.

ACTUALIZAR:

Actualicé el código anterior para reflejar los cambios que me ofrecieron miembros útiles.


32
2018-04-14 17:57


origen


Respuestas:


Esta función devuelve la clave principal del registro insertado: PDO :: lastInsertId Lo necesitarás para NEED_USERS_UID_FOR_HERE parámetro. Úselo justo después de la instrucción INSERT.

Desde que comenzó una transacción, los datos no se insertarán en ninguna tabla si se produce algún error siempre que use el motor InnoDB para sus tablas MySQL (MyISAM no admite transacciones).


18
2018-04-14 18:02