mysqli_stmt_bind_param() 当问号是查询的一部分时未提供数据

mysqli_stmt_bind_param() data not supplied when a question mark is a part of the query

类似的问题已经被问过很多次了,但是在阅读了几乎所有这些问题超过 5 个小时之后,我还没有找到适合我的问题的答案。

我不是经验丰富的 php / mysql 开发人员,但我使用 mysqli_stmt_bind_param() 函数处理过类似情况。

这里是查询:

$query = 'SELECT Recipes.* , Categories.* FROM `Recipes` JOIN `Categories` ON JSON_EXTRACT(Recipes.category, \'$.category\') = \'Category ?\' WHERE Categories.category = ?';

我使用这个 php 代码:

if ($stmt = mysqli_prepare($dbManager->getDBInstance(), $query)){

        mysqli_stmt_bind_param($stmt,"ii", $id, $id);

    }

因为我在客户端有一个模型,例如:

{
    "category" : "...",
    "recipes" : [{...},{...}]
}

错误是:致命错误:未捕获mysqli_sql_exception:没有为准备好的语句中的参数提供数据

我已经使用更多参数进行了类似的查询,没有任何错误:但是,这是我第一次使用 mysql 中的 JSON_EXTRACT 函数。

我认为错误是由 $.没有正确转义。要替换的参数引用同一个变量 $id,它是一个整数,在第一种情况下用于字符串插值 ('Category 1'),在 WHERE 子句后用作数字。

考虑一下,通过不使用 mysqli_stmt_bind_param,对 phpmyadmin returns 的相同查询是我想要的,但这会打开我的代码以进行 mysql 注入,我想避免。

此外,请注意,如果我只将一个参数传递给函数,脚本就会执行(结果错误),就像查询在某个时候被截断一样......我正确地转义了每个单引号,甚至尝试使用双引号,但错误始终相同。
任何关于如何防止注入和实现结果的提示将不胜感激,因为我真的无法自己弄清楚。
谢谢

您在 mysqli_stmt_bind_param() 的调用中有两个参数,但 $query 中只有一个占位符。第一个 ? 在引号内,因此按字面意思处理,而不是占位符。

您可以使用 CONCAT() 将字符串文字与占位符连接起来,因此将其更改为:

$query = '
    SELECT Recipes.* , Categories.* 
    FROM `Recipes` 
    JOIN `Categories` ON JSON_EXTRACT(Recipes.category, \'$.category\') = CONCAT(\'Category \', ?) 
    WHERE Categories.category = ?';

占位符只能表示完整的数据文字。简单来说——任何你会用引号(或数字)写的东西。所以它不应该是 'Category ?' 而只是 ? 类别可以在 PHP.

中连接
$query = 'SELECT * FROM `Recipes` JOIN `Categories` ON 
          JSON_EXTRACT(Recipes.category, \'$.category\') = ?
          WHERE Categories.category = ?';
$stmt = mysqli_prepare($dbManager->getDBInstance(), $query);
$category = "Category $id";
mysqli_stmt_bind_param($stmt,"si", $category, $id);