Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/video/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP-具有未知参数数的安全PDO准备语句_Php_Mysql_Sql_Pdo - Fatal编程技术网

PHP-具有未知参数数的安全PDO准备语句

PHP-具有未知参数数的安全PDO准备语句,php,mysql,sql,pdo,Php,Mysql,Sql,Pdo,*我在mysqli上看到了关于这个主题的问题,或者在PDO上看到了关于边缘案例的问题,但没有找到这个具体的问题(这让我很惊讶,但也许我不知道如何搜索) 在尝试使用PDO之前,我使用了简单的、不受保护的查询。我的prepare函数如下所示,简化了: static function prepareUpdate($table, array $arguments, array $filter) { $argumentsList = self::associateArguments($argume

*我在mysqli上看到了关于这个主题的问题,或者在PDO上看到了关于边缘案例的问题,但没有找到这个具体的问题(这让我很惊讶,但也许我不知道如何搜索)

在尝试使用PDO之前,我使用了简单的、不受保护的查询。我的prepare函数如下所示,简化了:

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','accountry'=>'Carpenter']
例如,对于$arguments,
['employeeId'=>518]
对于filter。假设$table是“workers”。通过一些简单的功能,它变成:

辩论者变成

`name` = 'John', `occupation` = 'Carpenter'
`employeeId` = 518
过滤列表变为

`name` = 'John', `occupation` = 'Carpenter'
`employeeId` = 518
因此,最后一个字符串变成:

UPDATE `workers` SET `name` = 'John', `occupation` = 'Carpenter' WHERE `employeeId` = 518;
这对我来说似乎很简单。然后,我尝试在PDO的prepare语句中使用类似的逻辑。但是我遇到了麻烦。也许是因为我不明白它背后的理念?或者只是技术问题

如果我理解正确的话,PDO需要使用bindValue()方法和after prepare()方法来防止注入。而且,我必须使用占位符(:姓名,:职业等)

问题是,如果我不知道我要找什么专栏,甚至不知道要找多少专栏,我该怎么做

我看到的大多数示例都包含一个非常预定义的语句:updatetablex SET`name`=:name WHERE`id`=:id-或者类似的语句

那么,如果我想使用数量可变的参数呢?我的理解是,我只能用一个属性替换一个:占位符,而不是更多属性(因此不需要引号),因此我不能准确地编写如下内容:

UPDATE :table SET :allParametersHere ;

我该怎么办?我没有一个明确的表,我想使用这个函数,更不用说一个合理的有效列列表来检查。如何创建一个能够处理不同参数量的包装器?

对于此类问题,使用
数据库查询生成器
解决方案会更好

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

<?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);

对于此类问题,
数据库查询生成器
解决方案会更好

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

<?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);

您尝试过这里的任何答案吗?--looks promisingalmost@Drew回答:因为您使用的是PDO,所以不需要使用
bindParam
bindValue
:只需将标记的值数组传递给
execute
方法。@Aenderei Dwarf在模板中存在参数数量可变的问题,没有约束力。相关:你试过这里的任何答案吗?--looks promisingalmost@Drew回答:因为您使用的是PDO,所以不需要使用
bindParam
bindValue
:只需将标记的值数组传递给
execute
方法。@Aenderei Dwarf在模板中存在参数数量可变的问题,不绑定。相关:我尝试过这样做,但你的解决方案更优雅。谢谢你的回答。我的问题是,这不会因为$key变量不会被转义而影响PDO的安全性吗?当然,从技术上讲,它应该来自开发人员,所以它应该是可信的,但我认为一切都需要安全的。除非我们手动逃逸。不信任自己的代码听起来很有趣,但如果这是一个接口原型呢?例如@DwarfVader只需确保它来自开发人员,或者更确切地说,来自代码。从代码中预定义的列表中获取密钥被认为是足够安全的。尽管您仍然可以格式化标识符。如果关键点基本上是由用户定义的,比如,条件更新或WHERE,只需再次过滤掉它们,但这仍然让人感到有点失望。你有没有想过使用ORM?然后代码可能是这样的:
Model::factory('Workers',['employeeId'=>518])->values($arguments)->save()
(来自Kohana的示例)我尝试过这样做,但您的解决方案更优雅。谢谢你的回答。我的问题是,这不会因为$key变量不会被转义而影响PDO的安全性吗?当然,从技术上讲,它应该来自开发人员,所以它应该是可信的,但我认为一切都需要安全的。除非我们手动逃逸。不信任自己的代码听起来很有趣,但如果这是一个接口原型呢?例如@DwarfVader只需确保它来自开发人员,或者更确切地说,来自代码。从代码中预定义的列表中获取密钥被认为是足够安全的。尽管您仍然可以格式化标识符。如果关键点基本上是由用户定义的,比如,条件更新或WHERE,只需再次过滤掉它们,但这仍然让人感到有点失望。你有没有想过使用ORM?然后代码可以如下所示:
Model::factory('Workers',['employeeId'=>518])->value($arguments)->save()
(来自Kohana的示例)