9

在我的脑海中,我有一个类似这样的查询:

$sort = isset($sort) ? sanitize($_sort) : 'id';

if ($result = $link->prepare("
    SELECT id, price
    FROM items
    ORDER BY ?
"))
{
    $result->bind_param("s", $sort);
    $result->execute();
    etc...
}

当我在不设置排序变量的情况下运行此代码块时,它运行时不会出现与?在 ORDER BY 子句中使用相关的错误,并且结果集显示在看似带有“ORDER BY id”的结果集中。

如果我将排序变量设置为“price ASC”之类的东西,我仍然会得到一个似乎是“ORDER BY id”而不是“ORDER BY price ASC”的结果集。

现在,如果我更改代码并像这样运行它:

$sort = isset($sort) ? sanitize($_sort) : 'id';

if ($result = $link->prepare("
    SELECT id, price
    FROM items
    ORDER BY $sort
"))
{
    $result->execute();
    etc...
}

它运行正确,结果集与我在 phpMyAdmin 中的查询相同。

这里到底发生了什么以及为什么查询没有按照我最初使用 bind_param 的意图运行。

在我看来,它应该可以工作,因为不会出现与此类使用相关的错误......但实际上它似乎不适用于 ORDER BY 子句。几乎就像它在运行 bind_param 时没有转换排序变量一样。

编辑:

对于任何有兴趣的人-

if (isset($sort))
{
    $acceptableSortValues = array('name', 'price ASC', 'price DESC');
    $sort = sanitize($sort);
    if (!in_array($sort, $acceptableSortValues))
    {
        $sort = 'name';
    }   
}
else
{
    $sort = 'name';
}

if ($result = $link->prepare("
    SELECT name, price
    FROM items
    ORDER BY $sort
"))
{
    $result->execute();
    etc...
}
4

1 回答 1

11

只有数据可以与占位符绑定。

列/表名是架构的一部分,不能绑定。(它产生“奇怪的结果”而不是简单地产生错误的事实是实现的一个特点。)

我建议使用列名白名单和受控字符串插值。

于 2012-08-18T18:17:15.423 回答