Как мой фильтр Ajax PHP не фильтрует записи с помощью PDO?

#jquery #ajax #filter #pdo #where-in

#jquery #ajax #Фильтр #pdo #где-в

Вопрос:

Поэтому я пытаюсь фильтровать записи, используя флажки с помощью 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 )

Комментарии:

1. Проверьте, нет ли ошибки SQL. В настоящее время вы работаете вслепую, без обработки ошибок.

2. @Mitya Смотри пример выше

3. Я не вижу никакой обработки ошибок в вашем коде. Вам нужно проверить, что SQL-запрос, который вы создаете, действителен. Все остальное на данный момент не имеет значения.

4. @Mitya У меня есть обработка ошибок в верхней части моего кода, которую я не включил. ini_set(‘display_errors’, ‘1’); ini_set(‘display_startup_errors’, ‘1’); error_reporting(E_ALL); В запросе нет ошибок.

5. Эти два кажутся очень неправильными: $merk = implode("','", $_POST['merk']); и $merk = "'".$merk."'"; . Разве это не должно быть $merk = implode(',', $_POST['merk']); , а затем не добавляйте одинарные кавычки в merk, например, сохраняйте его таким, какой он есть, из массива $_POST , поскольку 'data' и data не совпадают, и я предполагаю, что вы ищете позже.

Ответ №1:

Вы используете странные кавычки, например "','" , при анализе входных данных. Кроме того, вы не должны указывать фактический заполнитель в инструкции. После разговора в чате я понял, что проблема заключается в предложениях IN и bindParams() не поддерживает массивы.

Из документации для 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 amp;$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
}
 

Комментарии:

1. Так рад, что кто-то помог с проблемой фильтрации, с которой я сталкиваюсь уже более двух недель… Спасибо за отличный ответ. Теперь система фильтрации работает для ввода одного флажка. Но когда я пытаюсь фильтровать записи на основе двух входных данных, это не дает мне никаких записей. Смотрите пример выше

2. Ну, вам нужно обновить свой вопрос, указав, как фактические данные $ _POST выглядят для разных фильтров. Как я уже сказал, вы всегда можете написать мне по адресу cyclonecode@gmail.com или подключитесь к моему slack в join.slack.com/t/cyclonecode/shared_invite /… и я постараюсь тебе помочь. Думая, что было бы проще просто поговорить об этом вместо этого. Если вышесказанное помогло вам, пожалуйста, также дайте ему оценку =)

3. Ваш отредактированный ответ выше отлично работает! Спасибо, что помогли мне