我正在使用变量来指定表,字段/列和要搜索的值的动态查询。我已经在phpMyAdmin(手动键入查询)中以及在代码内部通过将变量串联成一个完整的查询来使查询在没有变量的情况下按预期工作。
但是,当我使用bindParam()
或bindValue()
绑定变量时,它将返回一个空数组。
这是我的代码:
function search_db($db, $searchTerm, $searchBy, $searchTable){
try{
$stmt = $db->prepare('
SELECT
*
FROM
?
WHERE
? LIKE ?
');
$stmt->bindParam(1, $searchTable);
$stmt->bindParam(2, $searchBy);
$stmt->bindValue(3, '%'. $searchTerm.'%');
$stmt->execute();
} catch(Exception $e) {
return array();
}
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// database initialization, creates the $db variable
require(ROOT_PATH . "include/database.php");
$matches = search_db($db, 'search term', 'myColumn', 'myTable');
var_dump($matches);
预期结果:数据库中的行数组
实际结果:一个空数组
最佳答案
是否可以使用PDO准备好的语句来绑定标识符(表或字段名)或语法关键字?
不幸的是,准备好的语句只能表示数据文字。因此,一个非常常见的陷阱就是这样的查询:
$opt = "id";
$sql = "SELECT :option FROM t WHERE id=?";
$stm = $pdo->prepare($sql);
$stm->execute(array($opt));
$data = $stm->fetchAll();
根据PDO设置,此查询将导致错误(在使用实际的预处理语句的情况下)或字段集中的文字字符串
'id'
(在模拟的Prepares情况下)。因此,开发人员必须自己照顾标识符-PDO对此无济于事。
为了使动态标识符安全,必须遵循2条严格的规则:
正确格式化标识符
对照硬编码的白名单进行验证。
要格式化标识符,必须应用以下2条规则:
将标识符括在反引号中。
将反引号加倍,以逃避它们。
进行这种格式化之后,可以安全地将$ table变量插入查询中。因此,代码将是:
$field = "`".str_replace("`","``",$field)."`";
$sql = "SELECT * FROM t ORDER BY $field";
但是,尽管这种格式足以满足ORDER BY之类的要求,但在大多数其他情况下,仍有可能进行另一种注入:让用户选择他们可以看到的表或字段,我们可能会揭示一些敏感信息,例如密码或其他个人数据。因此,始终最好根据允许值列表检查动态标识符。这是一个简单的示例:
$allowed = array("name","price","qty");
$key = array_search($_GET['field'], $allowed);
$field = $allowed[$key];
$query = "SELECT $field FROM t"; //value is safe
对于关键字,规则是相同的,但是当然没有可用的格式设置-因此,仅白名单是可能的,应该使用:
$dir = $_GET['dir'] == 'DESC' ? 'DESC' : 'ASC';
$sql = "SELECT * FROM t ORDER BY field $dir"; //value is safe
另请参见PHP文档中的该用户贡献的注释:User note on PDO::quote
关于php - 是否可以使用PDO准备好的语句来绑定(bind)标识符(表或字段名)或语法关键字?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54571652/