PHP not throwing error for multiple queries

123 Views Asked by At

I have some PHP code to execute multi queries and one of the queries has an error in it. But PHP is not detecting it. Here's the code

        $updateCategoriesQ = "DELETE FROM category_products WHERE product = $id; INSERT INTO category_products (category, products) VALUES ";
        foreach ($product['categories'] as $key) {
            $updateCategoriesQ .= "(".mysqli_real_escape_string($connect, $key)."', $id), "; //error is here in the quote
        }
        $updateCategoriesQ = rtrim($updateCategoriesQ, ', ');
        o($updateCategoriesQ);

        $updateCategories = mysqli_multi_query($connect, $updateCategoriesQ);
        if($updateCategories){
            o('query ok'); //receives this output (wrapper function for echo)
        }

The query that forms is

DELETE FROM category_products WHERE product = 1; INSERT INTO category_products (category, products) VALUES (1', 1), (2', 1)

The second query has an error but PHP says its ok. If I create an error in the first query (delete) then it does throws the error but not if the error is in the second query. Is there a different method of capturing error here?

3

There are 3 best solutions below

1
Barmar On

The documentation of mysqli_multi_query() says:

Returns FALSE if the first statement failed. To retrieve subsequent errors from other statements you have to call mysqli_next_result() first.

$updateCategories = mysqli_multi_query($connect, $updateCategoriesQ);
if($updateCategories){
    o('delete query ok');

    $insertCategories = mysqli_next_result($connect);
    if ($insertCategories) {
        o('insert query ok');
    } else {
        o('insert query failed: ' . mysqli_error($connect));
    }
} else {
    o('delete query failed: ' . mysqli_error($connect));
}
2
Whip On

Okay, with the help of @Barmar and this answer here's a good way to capture errors on subsequent queries.

        $updateCategories = mysqli_multi_query($connect, $updateCategoriesQ);
        if($updateCategories){
            do {
                mysqli_next_result($connect);
                $result = mysqli_store_result($connect);
                if (!$result) {
                   o(mysqli_error($connect));
                }
            } while (mysqli_more_results($connect));
        } else {
            o(mysqli_error($connect));
        }
0
Dharman On

Do not use mysqli_multi_query()! You can only use this query if you have no user input and even then it is really cumbersome and unnecessary.

Instead use prepared statements. This is the recommended and secure way.

// Add this before new mysqli() to enable error reporting
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$stmtDel = $connect->prepare('DELETE FROM category_products WHERE product = ?');
$stmtDel->bind_param('s', $id);
$stmtDel->execute();

$stmtInsert = $connect->prepare('INSERT INTO category_products (category, products) VALUES(?, ?)');
$stmtInsert->bind_param('ss', $key, $id);
foreach ($product['categories'] as $key) {
    $stmtInsert->execute();
}

As you can see here I have two separate queries and I execute the second one multiple times. This is faster, more secure and it will throw all the errors.