PHP Implode 但每个元素都用引号包裹

79
Assume I have an array:
 $elements = array('foo', 'bar', 'tar', 'dar');

我想构建一个DELETE IN的SQL查询:

 $SQL = "DELETE FROM elements
               WHERE id IN ('" . implode(',', $elements) . "')";
问题在于元素数组中的 id 没有被单独引用起来。例如查询看起来像这样:
 $SQL = "DELETE FROM elements
               WHERE id IN ('foo,bar,tar,dar');

最好的、最优雅的方法是如何修复这个问题?


1
非常小心,你很可能容易受到严重的SQL注入攻击。 - Brad
使用nickb提供的解决方案,最好的防止SQL注入的方法是什么?谢谢。 - Justin
7个回答

138

将引号添加到implode调用中:(我假设你的意思是implode

$SQL = 'DELETE FROM elements
           WHERE id IN ("' . implode('", "', $elements) . '")';

这将生成:

DELETE FROM elements WHERE id IN ("foo", "bar", "tar", "dar")

防止SQL注入的最佳方法是确保元素被正确转义。

一个简单的方法(但我没有测试过)是使用array_maparray_walk,并对每个参数进行转义,如下所示:

$elements = array();
$elements = array_map( 'mysql_real_escape_string', $elements);

非常好,那么根据Brad提出的解决方案,最好的防止SQL注入的方法是什么? - Justin
1
@Jusin 我已经编辑了我的答案,并提出了防止 SQL 注入的建议。 - nickb
6
最好的方法是使用预处理语句。链接分别为:http://php.net/manual/zh/pdo.prepared-statements.php 和 http://php.net/manual/zh/mysqli.prepare.php。 - Petah
2
不要使用mysql_函数。 - ryantxr

19
你可以使用array_walk函数来迭代数组中的所有元素,将元素的引用传递,并以以下方式添加引号。

php 7.4或更高版本

<?php

$arr = ['a','b','c'];

array_walk($arr, fn(&$x) => $x = "'$x'");

echo implode(',', $arr); // 'a','b','c'

PHP 7.3 或更早版本

<?php

$arr = ['a','b','c'];

array_walk($arr, function(&$x) {$x = "'$x'";});

echo implode(',', $arr); // 'a','b','c'

请解释一下为什么这是一个答案。对你来说可能很琐碎,但由于你没有添加任何解释,你的建议在使用上存在歧义。 - Glubus
2
链接是“澄清”。 - insign

4

您可以运行一个简单的array_map()函数,将字符串用引号括起来,然后将其包装在implode()中以添加逗号:

$array = ["one", "two", "three", "four"];

implode(",", array_map(function($string) {
    return '"' . $string . '"';
}, $array));

3

json_encode怎么样?

$arr=array("foo","bar","tar","dar");
$str=json_encode($arr);
echo $str;

结果: ["foo","bar","tar","dar"]


这是最好的答案。 - Ciprian
这是目前为止最好的答案!简短而快速!干杯! - dwbra

1
您也可以这样做。
$elements = array('foo', 'bar', 'tar', 'dar');

$data = '"' . implode('", "', $elements) . '"';

echo $data; // "foo", "bar", "tar", "dar" 

0

在顶部答案的基础上补充一点,即使您正在使用MySQLi,也可以使用对象方法callable形式通过使用array_map调用real_escape_string。这是一个示例,假设$conn是您的MySQLi连接:

$elements = array('foo', 'bar', 'tar', 'dar');
$cleanedElements = array_map([$conn, 'real_escape_string'], $ids);
$SQL = 'DELETE FROM elements WHERE id IN ("' . implode('", "', $elements) . '")';

请注意,array_map的第一个参数是一个数组,其中包含对象和方法名称。这与对数组中每个项目执行以下操作相同:
$newItem = $conn->real_escape_string($item);

0

我只想指出,顶部答案不会完全起作用。在您的implode末尾将缺少一个元素。

因此,改为:

DELETE FROM elements WHERE id IN ("foo", "bar", "tar", "dar")

您将获得:

DELETE FROM elements WHERE id IN ("foo", "bar", "tar", "dar)

请注意,结束元素“dar”现在缺少引号。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接