首页 > 解决方案 > 在 PHP 中使用数组制作参数化 SELECT 查询

问题描述

这是我在这里的第一篇文章。我阅读了很多类似的主题,但我没有找到令人满意的答案。

我无法使用数组制作参数化查询。

我的应用程序有某种过滤器。复选框代表配方所在的国家/地区,列表代表配方包含的产品。这些参数通过 AJAX 由两个数组(国家和列表)发送。我需要制作一个查询,从表“食谱”中选择所有记录,其中 kraj_pochodzenia = 数组“国家”中的参数,食谱包含成分 = 数组“列表”。

这是我的代码:

//query where we want filtering by ingredients list and country
if(isset($_POST['list']) && isset($_POST['country'])){ 
    $list = json_decode($_POST['list']);
    $list = array_map("htmlspecialchars", $list);
    $country = json_decode($_POST['country']);
    $country = array_map("htmlspecialchars", $country);

    //need statement here, for the rest ifs I will figure out :)

//query where we want filterin only by country
} else if (!isset($_POST['list']) && isset($_POST['country']) ) {
    $country = json_decode($_POST['country']);
    $country = array_map("htmlspecialchars", $country);

// query where we want only filtering by ingredients list 
} else if (isset($_POST['list']) && !isset($_POST['country'])) { 
    $list = json_decode($_POST['list']);
    $list = array_map("htmlspecialchars", $list);

} else {} 

这是我的数据库关系:

数据库关系

存在多对多的关系。许多食谱有许多不同的成分。Nazwa_skladnika = name_ingredient

@UPDATE
HTML CHECKBOXES,li 正在通过 AJAX 生成动态(在数据库中搜索产品,单击 datalist,添加到 ul):

<div class="col-lg-4">
              <div class="form-group">
                <p class="lead">Wybierz kraj potrawy!</p>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="japanCheck" value="japonia" name="checky[]">
                  <label class="form-check-label" for="japanCheck">Japonia</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="thaiCheck" value="tajlandia" name="checky[]">
                  <label class="form-check-label" for="thaiCheck">Tajlandia</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="indiaCheck" value="indie" name="checky[]">
                  <label class="form-check-label" for="indiaCheck">Indie</label>
                </div>
                <div class="form-check form-check-inline">
                  <input class="form-check-input" type="checkbox" id="chinaCheck" value="chiny" name="checky[]">
                  <label class="form-check-label" for="chinaheck">Chiny</label>
                </div>
                <p class="lead">Wprowadź produkt, który ma się zawierać w potrawie </p>
                  <input type="text" list="resultSearch" id="searchProduct" autocomplete="off" placeholder="np. papryka" name="products">
                  <span class="fa fa-search"></span>
                  <datalist id="resultSearch"></datalist>
                  <ul class="list-group" id="listProduct"></ul>
              </div>
          </div>

AJAX 用于发送带有复选框值和 li 值的数组:

$(document).ready(function(){
  $('.form-check-input').on('change', function(){//za kazda zmiana filtra od kraju niech sie ajax odpala i przeszukuje dane
    var listOfProduct = $("#listProduct li").map(function(){ // trzeba sprawdzic czy lista jest juz zrobiona
                      return $(this).text();
    }).get();
    var checkBoxes =  $('.form-check-input:checked').map(function(){
      return this.value;
    }).get();

    if(listOfProduct !== undefined && listOfProduct.length > 0){ // jezeli lista produktow jest zrobiona odpalamy ajaxa z filtrem kraju i listy

      $.ajax({
        type: "POST",
        url:"filtering.php",
        dataType:"JSON",
        data: {
          country:JSON.stringify(checkBoxes),
          list:JSON.stringify(listOfProduct)
        },
        success: function(data){
          //trzeba zrobic by zdjecie dodawalo do karuseli na tym napis przepisu i tagi z opis_przepisu
        }
      })
    }else{//pusta lista sprawdzamy same potrawy na podstwie kraju
      $.ajax({
        type: "POST",
        url:"filtering.php",
        dataType:"JSON",
        data: {
          country:JSON.stringify(checkBoxes),
        },
        success: function(data){
          //trzeba zrobic by zdjecie dodawalo do karuseli na tym napis przepisu i tagi z opis_przepisu
        }
      })
    }
  });
   $('#listProduct').on('click',function(){ // teraz ajax na zmainie listy
     var listOfProduct = $("#listProduct li").map(function(){
                       return $(this).text();
     }).get();
     var checkBoxes =  $('.form-check-input:checked').map(function(){// sprawdzic czy jest filtr kraju wybrany
       return this.value;
     }).get();
     if(checkBoxes !== undefined && checkBoxes.length > 0){
       $.ajax({
         type: "POST",
         url:"filtering.php",
         dataType:"JSON",
         data: {
           country:JSON.stringify(checkBoxes),
           list:JSON.stringify(listOfProduct)
         },
         success: function(data){
           //trzeba zrobic by zdjecie dodawalo do karuseli na tym napis przepisu i tagi z opis_przepisu
         }
       })
     }else{ // sam filtr z produktami ze wszystkic krajow
       $.ajax({
         type: "POST",
         url:"filtering.php",
         dataType:"JSON",
         data: {
           list:JSON.stringify(listOfProduct)
         },
         success: function(data){
           //trzeba zrobic by zdjecie dodawalo do karuseli na tym napis przepisu i tagi z opis_przepisu
         }
       })
     }
   })
})

@UPDATE2 - 解决方案
这是一个代码,PDO 是 imo 最简单的方法:

try{
          $pdo = new PDO("mysql:host=$host;dbname=$database;charset=utf8", $user, $password);

        }
      catch(PDOException $e){
          echo $e->getMessage();
        }


      if(isset($_POST['list']) && isset($_POST['country'])){ //query where we want filtering by ingre list and country
        $list = json_decode($_POST['list']);
        $list = array_map("htmlspecialchars", $list);
        $country = json_decode($_POST['country']);
        $country = array_map("htmlspecialchars", $country);
        $merge = array_merge($list,$country);
        $numberofparam = count($list);
        if(count($list)-1 >= 0 && count($country)-1 >= 0){
          $placeholders1 = str_repeat('?,', count($list) - 1)  . '?';
          $placeholders2 = str_repeat('?,', count($country) - 1) . '?';
          $stmt = $pdo->prepare("SELECT DISTINCT
                                 r.nazwa_przepisu, r.opis_przepisu, r.zdjecie_przepisu, r.przygotowanie_przepisu, r.kraj_pochodzenia, r.spis_produktow
                                 FROM recipes r
                                 JOIN reci_ingre ri on r.id_przepisu = ri.id_przepisu
                                 JOIN ingredients i on ri.id_skladnika = i.id_skladnika
                                 WHERE i.nazwa_skladnika IN ($placeholders1) AND (kraj_pochodzenia IN ($placeholders2))
                                 GROUP BY r.id_przepisu
                                 HAVING COUNT(r.id_przepisu) = $numberofparam
                                 ORDER BY COUNT(r.id_przepisu) DESC");
          $stmt->execute($merge);
          $data = $stmt->fetchAll();
          echo json_encode($data);
        }


      }else if(!isset($_POST['list']) && isset($_POST['country']) ){//query where we want filterin only by country
        $country = json_decode($_POST['country']);
        $country = array_map("htmlspecialchars", $country);

        if(count($country)-1 >= 0){
          $placeholders = str_repeat('?,', count($country) - 1) . '?';
          $stmt = $pdo->prepare("SELECT DISTINCT
                                 r.nazwa_przepisu, r.opis_przepisu, r.zdjecie_przepisu, r.przygotowanie_przepisu, r.kraj_pochodzenia, r.spis_produktow
                                 FROM recipes r
                                 WHERE kraj_pochodzenia IN ($placeholders)");
          $stmt->execute($country);
          $data = $stmt->fetchAll();
          echo json_encode($data);
      } exit();





      }else if(isset($_POST['list']) && !isset($_POST['country'])){ // query where we want only filtering by ingredients list
        $list = json_decode($_POST['list']);
        $list = array_map("htmlspecialchars", $list);
        $numberofparam = count($list);
        if(count($list)-1 >= 0){
          $placeholders = str_repeat('?,', count($list) - 1) . '?';
          $stmt = $pdo->prepare("SELECT DISTINCT
                                 r.nazwa_przepisu, r.opis_przepisu, r.zdjecie_przepisu, r.przygotowanie_przepisu, r.kraj_pochodzenia, r.spis_produktow
                                 FROM recipes r
                                 JOIN reci_ingre ri on r.id_przepisu = ri.id_przepisu
                                 JOIN ingredients i on ri.id_skladnika = i.id_skladnika
                                 WHERE i.nazwa_skladnika IN ($placeholders)
                                 GROUP BY r.id_przepisu
                                 HAVING COUNT(r.id_przepisu) = $numberofparam
                                 ORDER BY COUNT(r.id_przepisu) DESC");
          $stmt->execute($list);
          $data = $stmt->fetchAll();
          echo json_encode($data);
        }

      exit();
    }

标签: phpmysql

解决方案


@UPDATE2 - 解决方案这是一个代码,PDO 是 imo 最简单的方法:

try{
      $pdo = new PDO("mysql:host=$host;dbname=$database;charset=utf8", $user, $password);

    }
  catch(PDOException $e){
      echo $e->getMessage();
    }


  if(isset($_POST['list']) && isset($_POST['country'])){ //query where we want filtering by ingre list and country
    $list = json_decode($_POST['list']);
    $list = array_map("htmlspecialchars", $list);
    $country = json_decode($_POST['country']);
    $country = array_map("htmlspecialchars", $country);
    $merge = array_merge($list,$country);
    $numberofparam = count($list);
    if(count($list)-1 >= 0 && count($country)-1 >= 0){
      $placeholders1 = str_repeat('?,', count($list) - 1)  . '?';
      $placeholders2 = str_repeat('?,', count($country) - 1) . '?';
      $stmt = $pdo->prepare("SELECT DISTINCT
                             r.nazwa_przepisu, r.opis_przepisu, r.zdjecie_przepisu, r.przygotowanie_przepisu, r.kraj_pochodzenia, r.spis_produktow
                             FROM recipes r
                             JOIN reci_ingre ri on r.id_przepisu = ri.id_przepisu
                             JOIN ingredients i on ri.id_skladnika = i.id_skladnika
                             WHERE i.nazwa_skladnika IN ($placeholders1) AND (kraj_pochodzenia IN ($placeholders2))
                             GROUP BY r.id_przepisu
                             HAVING COUNT(r.id_przepisu) = $numberofparam
                             ORDER BY COUNT(r.id_przepisu) DESC");
      $stmt->execute($merge);
      $data = $stmt->fetchAll();
      echo json_encode($data);
    }


  }else if(!isset($_POST['list']) && isset($_POST['country']) ){//query where we want filterin only by country
    $country = json_decode($_POST['country']);
    $country = array_map("htmlspecialchars", $country);

    if(count($country)-1 >= 0){
      $placeholders = str_repeat('?,', count($country) - 1) . '?';
      $stmt = $pdo->prepare("SELECT DISTINCT
                             r.nazwa_przepisu, r.opis_przepisu, r.zdjecie_przepisu, r.przygotowanie_przepisu, r.kraj_pochodzenia, r.spis_produktow
                             FROM recipes r
                             WHERE kraj_pochodzenia IN ($placeholders)");
      $stmt->execute($country);
      $data = $stmt->fetchAll();
      echo json_encode($data);
  } exit();





  }else if(isset($_POST['list']) && !isset($_POST['country'])){ // query where we want only filtering by ingredients list
    $list = json_decode($_POST['list']);
    $list = array_map("htmlspecialchars", $list);
    $numberofparam = count($list);
    if(count($list)-1 >= 0){
      $placeholders = str_repeat('?,', count($list) - 1) . '?';
      $stmt = $pdo->prepare("SELECT DISTINCT
                             r.nazwa_przepisu, r.opis_przepisu, r.zdjecie_przepisu, r.przygotowanie_przepisu, r.kraj_pochodzenia, r.spis_produktow
                             FROM recipes r
                             JOIN reci_ingre ri on r.id_przepisu = ri.id_przepisu
                             JOIN ingredients i on ri.id_skladnika = i.id_skladnika
                             WHERE i.nazwa_skladnika IN ($placeholders)
                             GROUP BY r.id_przepisu
                             HAVING COUNT(r.id_przepisu) = $numberofparam
                             ORDER BY COUNT(r.id_przepisu) DESC");
      $stmt->execute($list);
      $data = $stmt->fetchAll();
      echo json_encode($data);
    }

  exit();
}

推荐阅读