使用mysqli准备ORDER BY的问题

时间:2015-01-31 21:16:02

标签: php mysql mysqli

我正在努力更新网站以避免任何MySQL注入攻击的可能性。这导致我使用mysqli与Php。

当我尝试在网站上执行搜索时,我现在收到此错误:

Fatal error: Call to a member function bind_param() on a non-object in ...

搜索旨在从文本框中获取用户输入,并在数据库中搜索包含用户输入的特定字符串的记录。我试图运行的代码如下:

$sql = "SELECT * FROM periodicals WHERE MATCH(author, title, type, keyword, citation) AGAINST (? IN BOOLEAN MODE) ORDER BY ? ? LIMIT ?,?";

$stmt = $conn -> prepare($sql);

$stmt -> bind_param("sssii", $param1, $param2, $param3, $param4, param5);

$param1 = $trimmed; //contains a keyword entered by user to search for
$param2 = $column;  // contains which column to sort by (selected by user)
$param3 = $sort;    // contains 'ASC' or 'DESC' for sorting (selected by user)
$param4 = (empty($s)) ? 0 : $s; //contains offset for LIMIT
$param5 = $limit; // contains number of values to retrieve

我使用var_dmup($stmt)并返回false,这意味着对prepare()的调用未成功。

我读到一个不正确的SQL查询可能会导致此错误,并通过直接在数据库上运行sql(带有值而不是?)来检查以确保查询正常工作,并且没有遇到任何错误或警告。

然后我做了一些实验。我认为我将问题缩小到SQL查询的ORDER BY ? ?部分,因为代码将运行并在第二个?更改为ASC或{{1时加载正确的结果并调整DESC以匹配如下:

bind_param()

$sql = "SELECT * FROM periodicals WHERE MATCH(author, title, type, keyword, citation) AGAINST (? IN BOOLEAN MODE) ORDER BY ? DESC LIMIT ?,?"; $stmt = $conn -> prepare($sql); $stmt -> bind_param("ssii", $param1, $param2, $param4, param5); 的值在代码前面设置为$param3DESC。在编写将值存储到ASC中的代码时,我在测试中使用var_dump()来确保这一点,所以我不相信它会在查询中输入不正确的值。

如果有人对我如何能够解决这个问题或出现什么问题有任何建议,我将非常感激。

2 个答案:

答案 0 :(得分:0)

order by的参数之间需要逗号。所以,如果你有两把钥匙,你会这样做:

ORDER BY ?, ?

但您希望第二个是ASCDESC。您不能直接将这些作为参数传递。您可以将它们构建到字符串中,这应该是安全的,因为您只能根据php中的逻辑放入ASCDESC。或者,您可以传入一个字符串并执行:

ORDER BY (CASE WHEN ? = 'DESC' THEN ? END) DESC,
         ? ASC

当第一个表达式的计算结果为true时,则使用该值。否则,所有值都为NULL - 第二个子句生效。

答案 1 :(得分:0)

如您所知,

bind_param用于阻止SQL Injection。它是通过确保您只能输入值而不是改变实际的SQL语句来实现的。

如果您尝试将ASCDESC作为参数加入,您会注意到无法完成。仅仅因为那意味着你正在改变SQL陈述。

您应该自行检查值并在查询中输入。

<?php
$ascOrDesc = ($uservalue=="DESC") ? "DESC" : "ASC";
$sql = "SELECT * FROM periodicals WHERE MATCH(author, title, type, keyword, citation) AGAINST (? IN BOOLEAN MODE) ORDER BY ? " . $ascOrDesc;
?>

请注意,如果您使用?作为ORDER BY类中的列名,那么您实际上并没有按列值进行排序。

如果您要输入Name作为列,则会按值'name'而不是列name对所有行进行排序。所以根本就没有排序,因为每一行都匹配相同的值。