使用PDO在GET变量中传递多个值

8 浏览
0 Comments

使用PDO在GET变量中传递多个值

我对PDO存在一个问题,我已经被这个问题困扰了相当长的时间,我真的很希望能得到一个答案。

以这个例子为例:

我正在将一个ID数组绑定到PDO语句中,以便在MySQL的IN语句中使用。

数组可以是这样的:$values = array(1,2,3,4,5,6,7,8);

安全的数据库变量应该是:$products = implode(',', $values);

所以,$products将是一个值为'1,2,3,4,5,6,7,8'的字符串。

语句将会是:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (:products)

当然,$products将会被绑定到语句中作为:products

然而,当语句被编译和绑定值时,它实际上会变成这样:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN ('1,2,3,4,5,6,7,8')

问题是它将IN语句中的所有内容作为一个字符串执行,因为我已经准备好了以逗号分隔的值来绑定到语句中。

实际上我需要的是:

SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (1,2,3,4,5,6,7,8)

我唯一能做到的就是将值直接放在字符串中而不绑定它们,然而我确信一定有更简单的方法来做到这一点。

0
0 Comments

问题的原因是在使用PDO时,无法直接将多个值传递给GET变量。根据之前提到的答案,有三种解决方法。

第一种方法是在查询中构建查询语句来处理变量大小的列表。例如,可以使用quoted、逗号分隔的列表和find_in_set函数来实现。然而,对于大数据集,这种方法会有很大的性能影响,因为表中的每个值都必须转换为字符类型。

第二种方法是创建一个用户定义的函数来解析逗号分隔的列表,这可能是三种方法中最好的选择,特别是如果有很多查询依赖于in(...)子句。

第三种方法是在绑定参数时,确保字符串中没有空格。

以上是对问题出现的原因和解决方法的整理。在使用PDO时,如果需要将多个值传递给GET变量,可以考虑使用这些方法来解决。

0
0 Comments

问题出现的原因是当需要在GET变量中传递多个值时,使用PDO进行查询时,如果不知道要绑定的变量数量,就会变得有些混乱。

解决方法是将sprintf和count智能地结合起来。通过使用sprintf函数,可以动态生成包含适当数量占位符的查询语句。然后,使用count函数来确定要绑定的变量的数量,并将其与生成的查询语句一起传递给PDO的prepare方法。

具体来说,可以按照以下步骤解决该问题:

1. 使用sprintf函数生成包含适当数量占位符的查询语句。例如,可以使用以下代码生成查询语句:

$query = sprintf("SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products IN (%s)", implode(',', array_fill(0, count($values), '?')));

这里的$values是包含要绑定的值的数组。

2. 使用count函数确定要绑定的变量的数量。例如,可以使用以下代码获取$values数组中的元素数量:

$numValues = count($values);

3. 使用PDO的prepare方法准备查询语句,并将生成的查询语句和要绑定的变量的数量传递给它。例如,可以使用以下代码准备查询:

$stmt = $pdo->prepare($query);
$stmt->execute($values);

这里的$pdo是PDO对象,$values是包含要绑定的值的数组。

通过这种方法,可以动态地在GET变量中传递多个值,并使用PDO进行查询,而不需要手动计算要绑定的变量的数量。这样,可以更方便地处理不确定数量的参数。

0
0 Comments

在使用PDO时,有时需要在GET变量中传递多个值。下面是解决这个问题的方法:

一种处理这种情况的好方法是使用`str_pad`在SQL查询中为每个值放置一个`?`。然后,将值的数组(在这种情况下是`$values`)作为`execute`方法的参数传递进去:

$sql = '
SELECT users.id
FROM users
JOIN products
ON products.user_id = users.id
WHERE products.id IN ('.str_pad('',count($values)*2-1,'?,').')
';
$sth = $dbh->prepare($sql);
$sth->execute($values);
$user_ids = $sth->fetchAll();

这样,您可以更好地使用预处理语句,而不是直接将值插入到SQL中。

如果只想要唯一的用户ID,而不是重复的用户ID,则建议将查询的第一行改为`SELECT DISTINCT users.id`。

为什么需要在`count()`上做`*2-1`而不仅仅是`-1`?

这是因为`str_pad`的第二个参数是"填充长度",以字符为单位。由于您想要在每个值之间放置一个问号和一个逗号,所以计算出来的长度是`count($values)*2-1`。如果您愿意,也可以使用`str_repeat('?,',count($values)-1).'?'`。

我更喜欢使用`implode(',', array_fill(1,count($values),'?'))`,因为这样减少了出错的可能性,并且不需要单独处理最后一个元素。

您还可以使用`str_repeat()`,它可能是列出的方法中最高效的:`rtrim(str_reapeat('?,', count($values)), ',')`。

什么情况下直接在查询中放置变量是一个好主意?我们真的要为SQL注入防范措施而争论吗?为什么一个主张不应该这样做的解决方案会有17个赞成票?

你理解代码有误。它并没有将变量直接放在查询中。这正是这个解决方案的关键。它为每个变量放置一个问号,以便PDO可以准备实际的语句。是的,我们喜欢PDO的安全措施,这个解决方案提供了一种使用它们的方法。

`implode(',', array_fill(0, count($values), '?'))`

0