【问题标题】:How is my Ajax PHP filter not filtering records with PDO?我的 Ajax PHP 过滤器如何不使用 PDO 过滤记录?
【发布时间】:2021-04-22 01:38:19
【问题描述】:

所以我正在尝试使用带有 Ajax 和 PHP 的复选框来过滤记录。我正在尝试使用 PDO 过滤记录,因为它是最安全的选择。我想知道为什么过滤系统只在选择一个复选框而不是更多时过滤。

这是我的代码:

        if(isset($_POST['merk'])) 
        { 
            // Pretty sure you have the following format 1,2,3,4 and not '1','2','3','4'
            $merk = implode(',', $_POST['merk']);
            if (preg_replace('/[^A-Za-z0-9\-]/', '', $merk)) {
                // Notice that placeholders should not be quoted
                $sql .= ' AND merk IN(:merk)';
            }
        }

        if(isset($_POST['brandstof'])) 
        {
            $brandstof = implode(',', $_POST['brandstof']);
            if (preg_replace('/[^A-Za-z0-9\-]/', '', $brandstof)) {
                $sql .= ' AND brandstof IN(:brandstof)';
            }
        }

        if(isset($_POST['carrosserie'])) 
        {
            $carrosserie = implode(',', $_POST['carrosserie']);
            if (preg_replace('/[^A-Za-z0-9\-]/', '', $carrosserie)) {
                $sql .= ' AND carrosserie IN(:carrosserie)';
            }
        }

如果选中复选框merk,则代码将执行。查询可能有问题吗?

//We prepare our SELECT statement.
$statement = $pdo->prepare($sql);
        
if(isset($_POST['merk']))
{
  $statement->bindParam(":merk", $merk);
  // $params[] .= $merk;
}

if(isset($_POST['brandstof']))
{
  $statement->bindParam(":brandstof", $brandstof);
  // $params[] .= $brandstof;
}

if(isset($_POST['carrosserie']))
{
  $statement->bindParam(":carrosserie", $carrosserie);
  // $params[] .= $carrosserie;
}
    
$statement->execute();

此代码过滤一个复选框输入,但在选中两个复选框时停止过滤。请参阅下面的示例。

所以我的 POST 数据如下所示:Array ( [0] => BMW [1] => Skoda )

【问题讨论】:

  • 检查 SQL 错误。你目前在盲目工作,没有错误处理。
  • @Mitya 见上面的例子
  • 我在您的代码中看不到任何错误处理。您需要检查您正在构建的 SQL 查询是否有效。在这一点上,其他一切都无关紧要。
  • @Mitya 我的代码顶部有错误处理,但我没有包括在内。 ini_set('display_errors', '1'); ini_set('display_startup_errors', '1');错误报告(E_ALL);查询中没有错误。
  • 这两个似乎非常错误:$merk = implode("','", $_POST['merk']);$merk = "'".$merk."'";。这不应该是$merk = implode(',', $_POST['merk']);,然后不要在merk中添加单引号,例如保持它来自$_POST数组,因为'data'data不一样,我猜你正在寻找后者.

标签: jquery ajax filter pdo where-in


【解决方案1】:

您在解析输入时使用了奇怪的引号,例如 "','"。此外,您不应在语句中引用实际的占位符。 在聊天中我意识到问题在于 IN 子句和 bindParams() 不支持数组。

来自documentation 用于 PDOStatement::execute:

input_parameters 一个包含尽可能多元素的值数组 正在执行的 SQL 语句中的绑定参数。所有值都是 被视为 PDO::PARAM_STR。

多个值不能绑定到单个参数;例如,它 不允许将两个值绑定到一个命名参数 IN() 子句。

为了解决这个问题,您需要将代码更改为以下内容:

// Enable error reporting to spot any warnings and errors.
ini_set('display_errors', true);
error_reporting(E_ALL);

$params = array();

// Creates an IN clause with placeholders and stores parameters
function createInParam(array $data, $name, $query, array &$params) {
  $query .= " AND $name IN (";
  foreach ($data as $key => $value) {
    $params[$name . '_' . $key] = $value;
    $query .= ":${name}_${key},";
  }
  return rtrim($query, ',') . ')';
}

// Bind all parameters to statement
function bindParams($statement, array $params) {
  foreach ($params as $key => $value) {
    $statement->bindParam(":$key", $params[$key]);
  }
}

if (isset($_POST['merk'])) { 
  $merk = implode(',', $_POST['merk']);
  if (preg_replace('/[^A-Za-z0-9\-]/', '', $merk)) {
    $data = explode(',', $merk);
    $sql = createInParam($data, 'merk', $sql, $params);
  }
}

if (isset($_POST['brandstof'])) {
  $brandstof = implode(',', $_POST['brandstof']);
  if (preg_replace('/[^A-Za-z0-9\-]/', '', $brandstof)) {
    $data = explode(',', $brandstof);
    $sql = createInParam($data, 'brandstof', $sql, $params);
  }
}
    
if (isset($_POST['carrosserie'])) {
  $carrosserie = implode(',', $_POST['carrosserie']);
  if (preg_replace('/[^A-Za-z0-9\-]/', '', $carrosserie)) {
    $data = explode(',', $carrosserie);
    $sql = createInParam($data, 'carrosserie', $sql, $params);
  }
}

// Then bind all parameters and execute
bindParams($statement, $params);
if ($statement->execute()) {
  // Success
}

做同样事情的另一种方法是:

$params = array();


if (isset($_POST['merk'])) { 
  $merk = implode(',', $_POST['merk']);
  if (preg_replace('/[^A-Za-z0-9\-]/', '', $merk)) {
    $inClause = implode(',', array_fill(0, count($_POST['merk']), '?'));
    $sql .= " AND merk IN ($inClause)";
    $params = array_merge($params, explode(',', $merk));
  }
}

if (isset($_POST['brandstof'])) {
  $brandstof = implode(',', $_POST['brandstof']);
  if (preg_replace('/[^A-Za-z0-9\-]/', '', $brandstof)) {
    $inClause = implode(',', array_fill(0, count($_POST['brandstof']), '?'));
    $sql .= " AND brandstof IN ($inClause)";
    $params = array_merge($params, explode(',', $brandstof));
  }
}
    
if (isset($_POST['carrosserie'])) {
  $carrosserie = implode(',', $_POST['carrosserie']);
  if (preg_replace('/[^A-Za-z0-9\-]/', '', $carrosserie)) {
    $inClause = implode(',', array_fill(0, count($_POST['carrosserie']), '?'));
    $sql .= " AND carrosserie IN ($inClause)";
    $params = array_merge($params, explode(',', $carrosserie));
  }
}

if ($statement->execute($params)) {
  // Success
}

【讨论】:

  • 很高兴有人帮助我解决了我两个多星期以来面临的过滤问题......感谢您提供了很好的答案。过滤系统现在适用于一个复选框输入。但是当我尝试根据两个输入过滤记录时,它没有给我任何记录。见上面的例子
  • 那么你需要用实际的 $_POST 数据如何寻找不同的过滤器来更新你的问题。就像我说的,您可以随时通过 cyclonecode@gmail.com 给我发电子邮件,或者通过join.slack.com/t/cyclonecode/shared_invite/… 联系我的 slack,我会尽力帮助您。认为只是谈论这个可能会更容易。如果以上内容对您有帮助,请也给它一个upvote =)
  • 您在上面编辑的答案效果很好!谢谢你帮助我
猜你喜欢
  • 2018-04-26
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2017-08-18
  • 2017-09-19
  • 1970-01-01
相关资源
最近更新 更多