Can't use more than one STMT query for mysqli

末鹿安然 提交于 2020-07-04 04:23:49

问题


I'm trying to generate an users creation page and I make a validation to determine if the user already exists, for that I use the next code:

here i insert the user and his password to the table USERS

mysqli_stmt_bind_param($guardar_usuario, 'ss', $usuario,$encriptar);
mysqli_stmt_execute($guardar_usuario);

here i reuse the variable $user to recover the new id user created

$consulta = "SELECT id_usuario FROM usuario WHERE usuario = '$usuario' ORDER BY fecha_registro DESC LIMIT 1";
$ultimo_registro = mysqli_prepare($connect,$consulta);
mysqli_stmt_execute($ultimo_registro);
mysqli_stmt_bind_result($ultimo_registro, $id_usuario_creado);
mysqli_stmt_fetch($ultimo_registro);

I insert the extra data to a table named PERSONAS

$guardar_persona = mysqli_prepare($connect, "INSERT INTO persona (id_usuario, nombre, email) VALUES (?, ?, ?)");        
mysqli_stmt_bind_param($guardar_persona, 'iss',  $ultimo_registro, $nombre_usuario, $email_usuario);            
mysqli_stmt_execute($guardar_persona);

My problem is that the second query, the data insert to the table PERSONAS doesn't work, but if I remove the first query which makes the insert to the table USERS, this query works perfectly, so I dont know if is there a rule to make this work?

Sorry if its a quite newbie question, just started to work this way to try to prevent as much as possible data inyection.


回答1:


When executing prepared statements mysqli uses unbuffered queries by default. This is a very confusing behaviour, but it means that the results are not sent automatically to PHP. MySQL server stores the results on the server and waits for PHP to retrieve them. As long as there is still more results to be fetched, you can't execute another query.

To fix this you need to call mysqli_stmt_store_result() or you need to get all results.

In your case the simple option would be to add store_result and be done with it.

$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$ultimo_registro = mysqli_prepare($connect,$consulta);
mysqli_stmt_bind_param($ultimo_registro, 's', $usuario);
mysqli_stmt_execute($ultimo_registro);
mysqli_stmt_store_result($ultimo_registro);
mysqli_stmt_bind_result($ultimo_registro, $id_usuario_creado);
mysqli_stmt_fetch($ultimo_registro);

However, it would be much easier for you if you stop using mysqli functions directly. Even a simple wrapper function can help you avoid all this mysqli mess.

function safeQuery(mysqli $db, string $sql, array $params = []): ?array {
    $stmt = $db->prepare($sql);
    if ($params) {
        $stmt->bind_param(str_repeat("s", count($params)), ...$params);
    }
    $stmt->execute();
    if ($result = $stmt->get_result()) {
        return $result->fetch_all(MYSQLI_BOTH);
    }
    return null;
}

Then you can abstract your whole prepared statement to just one line of code:

$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$result = safeQuery($connect, $consulta, [$usuario]);
if ($result) {
    $id_usuario_creado = $result[0]['id_usuario'];
}

You can even write a second function which will fetch only a single value from the prepared statement.

function fetchSingle(mysqli $db, string $sql, array $params = []) {
    $stmt = $db->prepare($sql);
    if ($params) {
        $stmt->bind_param(str_repeat("s", count($params)), ...$params);
    }
    $stmt->execute();
    if ($result = $stmt->get_result()) {
        return $result->fetch_row()[0];
    }
    return null;
}

This can be used with LIMIT 1 when you only want to fetch a single value.

$consulta = "SELECT id_usuario FROM usuario WHERE usuario = ? ORDER BY fecha_registro DESC LIMIT 1";
$id_usuario_creado = fetchSingle($connect, $consulta, [$usuario]);


来源:https://stackoverflow.com/questions/62666651/cant-use-more-than-one-stmt-query-for-mysqli

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!