【问题标题】:How to retrieve a default row when a mysqli_stmt_fetch fails?mysqli_stmt_fetch 失败时如何检索默认行?
【发布时间】:2011-03-10 18:55:15
【问题描述】:

我有一个简单的 PHP 脚本,它根据 URL GET 参数从 MySQL 数据库中提取一行,只是一个称为 ID 的 int。

如果 GET 参数是数据库的无效 ID,例如有人输入的 int 不是数据库中的行,或者他们尝试输入字符或其他内容,我想显示默认记录.

以下代码确实有效,但我觉得它是糟糕的代码。我只是不确定为什么,或者我应该做什么。我知道我应该在运行数据库查询之前验证 ID 是否为 int,但这并不能解决使用无效 ID 的整数时该怎么做。

所以要让这个问题成为一个正确的问题,我应该如何从返回 false 的 mysqli_stmt_fetch 中恢复?

放轻松,我知道我是个小胖子 :-)

$ID = (int)$_GET["id"];

$query = "SELECT `col1`, `col2`, `col3` FROM `table` WHERE `ID` = ?";

if ($stmt = mysqli_prepare($connection, $query))
{
    mysqli_stmt_bind_param($stmt, "i", $ID);
    mysqli_stmt_execute($stmt);
    mysqli_stmt_bind_result($stmt, $var1, $var2, $var3);
    if (!mysqli_stmt_fetch($stmt))
    {   
        $ID = 1; //A record I know exists and will always exist
        mysqli_stmt_bind_param($stmt, "i", $ID);
        mysqli_stmt_execute($stmt);
        mysqli_stmt_bind_result($stmt, $var1, $var2, $var3);
        mysqli_stmt_fetch($stmt);
    }
    mysqli_stmt_close($stmt);
}

好的,通过一些反馈和实验,我在 PHP 中将 ID 转换为 int 并将 SQL 查询更改为:

SELECT `col1`, `col2`, `col3`
FROM `table`
WHERE `ID` = ?
UNION
SELECT `col1`, `col2`, `col3`
FROM `table`
WHERE `ID` = 1
LIMIT 1

这适用于我能想到的所有情况,并且似乎是安全的。任何问题?比我的更好吗?

【问题讨论】:

    标签: php mysql security parameterized-query


    【解决方案1】:

    首先检查传入的 $ID 是否为 char 等,并将其设置为在您的表中永远不会作为 ID 的值,然后使用查询

    SELECT col1, col2, col3 FROM table WHERE ID = :id
    union all 
    SELECT col1, col2, col3 FROM table WHERE ID = 1 /* may :defaut_id if */
    where not exist (select 1 from table WHERE ID = :id)
    

    【讨论】:

    • 我最终选择了这个的变体。在 PHP 中将 ID 转换为 int 意味着我的 ID 总是为 0(如果 ID 字符串以非数字开头)或任何以 int 开头的字符串。
    【解决方案2】:

    假设默认记录有一个id,那么它可以在单个查询中完成:

    select ...
    from ...
    where (id = ?) or (id = $default_id)
    

    只需将默认 ID 硬编码到查询字符串中。

    【讨论】:

    • 今天试了一下。它在 ID 无效时显示默认行,但在 ID 有效时也显示默认行(在这种情况下默认 ID 为 1)。
    • 我想一个 xor 而不是 or 也会处理这个问题。 “一个或另一个,但不是两者”。
    • 我也尝试过 XOR,但在 MySQL 5.1 上,当与 phpMyAdmin 一起使用时,它会在 ID 有效时返回两行。而且,由于它默认按 ID 排序,因此我不能使用限制,因为它会返回默认值。为了解决这个问题,我需要订购结果,这可行,但我不能随意更改默认 ID。嗯。
    猜你喜欢
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 2015-02-17
    • 1970-01-01
    相关资源
    最近更新 更多