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句での使用に関連するエラーなしで実行され、結果セットが「ORDERBYid」の結果セットのように表示されます。

並べ替え変数を「priceASC」のようなものに設定しても、「ORDERBYpriceASC」ではなく「ORDERBYid」のように見える結果セットが得られます。

ここで、コードを変更して次のように実行すると、次のようになります。

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

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

正しく実行され、phpMyAdminのクエリと同じ結果セットが得られます。

ここで正確に何が起こっているのか、そしてなぜbind_paramを使用して最初に意図したようにクエリが実行されないのか。

私の考えでは、このような使用に関してエラーが発生しないため、機能するはずです...しかし、実際には、ORDERBY句では機能しないようです。bind_paramの実行中にsort変数を変換していないようです。

編集:

興味のある方へ-

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 に答える