PHP - 使用未知数量的参数保护PDO预处理语句

时间:2018-02-20 22:44:36

标签: php mysql sql pdo

*我看到了关于这个主题的问题,关于mysqli或PDO的边缘情况,但没有找到这个具体的问题(这让我感到惊讶,但也许我不知道如何搜索) < / p>

在尝试使用PDO之前,我使用了简单的,不受保护的查询。我的准备功能看起来像这样,简化:

static function prepareUpdate($table, array $arguments, array $filter) {
    $argumentsList = self::associateArguments($arguments);
    $filterList = self::associateArguments($filter);

    $query = "UPDATE `$table` SET $argumentsList WHERE $filterList;";
    return $query;
}

$ arguments和$ filter是关联数组:['name' => 'John', 'occupation' => 'Carpenter']表示$ arguments,['employeeId' => 518]表示filter。假设$ table是'worker'。通过一些简单的功能,它变成:

argumentsList成为

`name` = 'John', `occupation` = 'Carpenter'

filterList变为

`employeeId` = 518

所以最终的字符串变为:

UPDATE `workers` SET `name` = 'John', `occupation` = 'Carpenter' WHERE `employeeId` = 518;

这对我来说似乎很简单。然后,我尝试在PDO的准备语句中使用类似的逻辑。但是我遇到了麻烦。也许是因为我不理解它背后的预期哲学?或者只是技术性。

如果我理解正确的话,PDO需要使用bindValue()方法,并且在prepare()之后可以防止注入。而且,我必须使用占位符(:名称,:职业等)。

问题是,如果我不知道我要查找哪些列,甚至有多少列,我该怎么做呢?

我看到的大多数示例都包含一个非常预定义的语句:UPDATE tableX SET`name` =:name WHERE`id` =:id - 或者沿着那些行的东西。

那么如果我想使用可变数量的参数呢?我的理解是我只能用一个属性替换一个:占位符,而不是更多(因此不需要引号的原因),所以我不能写出类似的东西:

UPDATE :table SET :allParametersHere ;

我该怎么做?我没有一个明确的表,我想使用此函数,更不用说要检查的有效列的合理列表。我如何创建一个可以使用不同参数量的包装器?

1 个答案:

答案 0 :(得分:2)

对于此类问题,database query builder解决方案会更好。

回到问题:您知道参数的数量,因此您可以创建查询模板。

<?php
$wq = $pq = [];
$allowed_keys = ['name', 'occupation', '...'];

foreach ($arguments AS $key => $value) {
  if(in_array($key, $allowed_keys))
    $pq[] = "$key = :$key" ;
  else throw new Exception('Go away hacker!');
}
foreach ($filter AS $key => $value)
  if(in_array($key, $allowed_keys))
    $wq[] = "$key = :$key" ;

$q = "UPDATE $table SET ". join(', ', $pq);
if(!empty($wq))
  $q .= 'WHERE '. join(' AND ', $wq);

在结果中,您可以获得如下的查询模式:

UPDATE workers SET name = :name, occupation = :occupation WHERE employeeId = :employeeId;

允许这样的折叠(如果你有&#34;安全&#34;这些表的键)

$allowed_keys或更好$allowed_column_names