【问题标题】:Explode/Implode List for Mysql WHERE IN ()Mysql WHERE IN () 的爆炸/内爆列表
【发布时间】:2014-12-18 13:57:44
【问题描述】:

我真的被这个卡住了。

我正在尝试将代码列表传递给 MySql 语句,但格式不正确。

我的列表来自一个名为“uniquecode”的表单 textarea

文本区域中的示例代码(全部在新行上)为:

fg3456 tg7844 de3902 ..等

我尝试通过以下方式分解和内爆列表:

$ar = $_POST['uniquecode']
$in = "'".implode("','", explode("\n", $ar))."'";

然后将 $in 的结果传递给 Mysql 语句:

$sql = "SELECT code, size, price from stock WHERE code IN ($in)";

当我回显 $sql 时,我得到以下信息:

SELECT housecode, name, cost, size, price FROM stock where code IN ('fg3456 ','tg7844 ', ','de3902')

您只能看到最后一项,“de3902”的格式正确。注意列表中的第一项有一个空格,然后是一个单引号,然后是一个逗号:'fg3456',

由于这个问题,当我尝试从查询中循环遍历结果集时,只返回最后一项:

$result = $mysqli->query($sql); 
if ($result = mysqli_query($mysqli, $sql)) {
        while($row = $result->fetch_array()) {
            $code = $row['code'];
            $name = $row['name'];
            $size = $row['size'];
            $price = $row['price'];
        }   

 echo $code; //returns last item in the list: de3902

所以我的问题是如何将列表分解/分解为 Mysql 查询的 IN 子句的正确格式,以便正确读取并返回所有代码???

SELECT code, name, size, price from stock WHERE code IN ('fg3456','tg7844','de3902')

亲切的问候

【问题讨论】:

  • 正确的方法(在我看来......)是循环您的值并为每个值添加一个问号,然后在您准备好语句后将值绑定到这些占位符。现在你有一个 sql 注入问题。
  • 在单独的 var 中分解,进行修剪并将它们添加到内爆中,前提是修剪长度 > 0
  • 请将var_dump($_POST['uniquecode']) 的输出发布为从浏览器页面源复制而来,而不是在屏幕上呈现。你有一些虚假的东西(我认为不是额外的换行符)破坏了你的implode(),也许可以用arary_filter()纠正。但是需要采取措施来保护它免受 SQL 注入。
  • var_dump($ar) 结果:string(23) "fg3456 tg7844 de3902"
  • @Hexana 显示的字符串只有 20 个字符,所以也许你应该使用 preg_split() 来代替多个空格或换行符。

标签: php mysqli explode implode


【解决方案1】:

如 cmets 中所述,我将遍历您的值并为每个值添加一个问号,然后在您准备好语句后将这些值绑定到这些占位符。现在你有一个 sql 注入问题。

但是,为了确保您在收到的输入中获得您想要的字符串,您可以使用 preg_split() 在多个空格、制表符或换行符上展开。

对于example

$st = trim(" \n fg3456   tg7844  \n  \n de3902  \n ");
$ar = preg_split('#\s+#', $st);
var_dump($ar);
$in = "'".implode("','", $ar)."'";
var_dump($in);

结果:

array(3) {
  [0]=>
  string(6) "fg3456"
  [1]=>
  string(6) "tg7844"
  [2]=>
  string(6) "de3902"
}
string(26) "'fg3456','tg7844','de3902'"

您可以使用此部分的第一部分来准备声明:

$st = trim(" \n fg3456   tg7844  \n  \n de3902  \n ");
$ar = preg_split('#\s+#', $st);
$in = trim(str_repeat('?,', count($ar)), ',');
$sql = "SELECT code, size, price from stock WHERE code IN ($in)";
var_dump($sql);

结果:

string(57) "SELECT code, size, price from stock WHERE code IN (?,?,?)"

顺便说一句,我个人会使用 PDO,因为这会使绑定更容易。

【讨论】:

  • 宾果游戏!!!智能饼干。这一行成功了 $ar = preg_split('#\s+#', $st);太感谢了。不过,我确实需要对注入问题进行排序:)
【解决方案2】:

你为什么要在\n 上爆炸,看来你应该在空间(' ') 上爆炸。否则,内爆看起来不错。

或者,您可以使用preg_replace 将任意数量的空格替换为(引号逗号引号)。 $in = "'" . preg_replace('/\s+/',"','", $ar) . "'";.

【讨论】:

  • 已尝试:$ar = "'" 。 preg_replace('/\s+/,"','",' $ar) 。 "'" ;但给了我一个解析错误!
  • 应该是$in=...,我来编辑。哦,我错过了正则表达式的引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-26
  • 2015-06-11
  • 2016-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多