Как динамически привязать параметры SQL?

#php #sql #database #filter

#php #sql #База данных #Фильтр

Вопрос:

Я хочу создать веб-сайт, на котором я могу показывать действия. Я хочу создать функцию фильтрации на основе местоположения и дат.

Я использую этот запрос для фильтрации дат:

 function selectAllActivities($date = false, $locations = false){
    $sql = "SELECT * FROM `activities`
            INNER JOIN `locations` ON `activities`.`location_id` = `locations`.`id`
            WHERE 1";

    if (!empty($date)){
      $sql .=  " AND `activities`.`start` >= :date AND `activities`.`start` < :next_day";
    }
    if (!empty($locations)){

      }

    }
    $stmt = $this->pdo->prepare($sql);

    if ($date){
      $dateTime = date("Y-m-d", strtotime($date));
      $dateTimeTomorrow= date("Y-m-d", strtotime($date.' 1 day'));
      $stmt->bindValue(':date', $dateTime);
      $stmt->bindValue(':next_day', $dateTimeTomorrow);
    }

    $stmt->execute();
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
  

Для местоположений у меня есть массив с выбранными датами в $ locations, но я не знаю, как динамически привязывать параметры к запросу, когда пользователи выбирают более 1 местоположения для фильтрации.

Вот как я хочу, чтобы это было жестко закодировано:

 SELECT * FROM `activities` WHERE 1 AND `location_id` IN (:location_id_0, :location_id_1, :location_id_2)

$stmt->bindValue(':location_id_1', $locations[0]);
$stmt->bindValue(':location_id_2', $locations[1]);
$stmt->bindValue(':location_id_3', $locations[2]);
  

Я думаю, мне нужно использовать функцию foreach, но я не могу понять, как это сделать.

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

1. @Qirel Да, он входит в виде массива

2. Я заметил это из последнего фрагмента кода сразу после комментария, поэтому я удалил комментарий 🙂

Ответ №1:

Вам понадобятся два простых цикла foreach, подобных этому:

 if (is_array($locations)) {
    $placeHolders = [];        
    foreach ($locations as $key => $location) {
        $placeHolders[$key] = ':location_id_'.$key;
    }
    $sql .= ' AND `location_id` IN ('.implode(', ',$placeHolders).')';
}

$stmt = $this->pdo->prepare($sql);

if (is_array($locations)) {
    foreach ($locations as $key => $location) {
        $stmt->bindValue($placeHolders[$key], $location);
    }
}
  

Когда $locations значение не пусто, вы перебираете его массив. Используя $key этот массив, вы создаете $placeHolders массив для вашего запроса MySQL.

После этого вы готовите инструкцию.

Затем вы привязываете местоположения к оператору, используя $placeHolders массив.

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

1.Используя это, вы завершаете генерацию запроса в $sql после того, как вы уже привязали значения, поэтому вам нужно разделить создание запроса и привязки, используя одно и то же условие, но разные этапы выполнения.