2014-10-28 1 views
5

사용자의 기준에 따라 제품 페이지를 작성하려고합니다. 다음 필드는 기본적으로 전달됩니다MySQL 추가 매개 변수를 기반으로 행 반환 PDO

  • qString
  • 최대 가격/최소 가격은
  • minDate/maxDate (검색 할 (표에 가격 사이에 할) (제품 이름/설명이 일치합니다) 제품 가용성 사이의 날짜)

위의 값은 나에게 반환 값을 제공합니다.

필드의 다음 커플은 선택 사항이며 카테고리를 기반으로 jQuery를 통해 추가 :

  • 카테고리 : (이 여전히 작동) CATEGORY_ID deals.deals_category_id 다시 일치

기반 카테고리에는 프런트 엔드 내에서 동적으로 표시 될 추가 속성 (예 : 서비스 제공 업체, 제조업체가있는 모바일 거래)이있을 수 있습니다. 여기에서 클라이언트는 체크 박스를 통해 관심있는 제조업체와 서비스 제공 업체를 선택할 수 있습니다.

내 테이블이 포함되어

  • 비교 (A deal_category_id와 제품을 포함)
  • 카테고리 (모든 거래는 범주에 연결되어 있습니다)
  • Category_attributes (카테고리 별 추가 속성을 제품이됩니다. 범주 내에로드되면 추가 속성 선택자와 함께 제공됩니다.
  • Deal_attribute_options (속성을 기반으로하는 관계 링크 된 옵션 포함 (속성이 서비스 공급자가 될 수있는 위치 및 속성 opti AT는 & T, t-Mobile 등)을 가질 수 있습니다.
  • Deal_attribute_values ​​제품을 만들 때 선택한 속성 옵션의 값이 있습니다. 새 휴대 전화를 만들고 휴대 전화 카테고리를 선택한다고 가정하면 제품에서 attribute_options 값을 지정해야하며 목록이 수신됩니다. 모바일 네트워크 또는 제조업체의 제품 제조업체와 해당 제조업체에 제품 제조업체를 연결하십시오.

지금까지 필자는 데이터베이스에 각각 범주에 연결되어 있고 연결된 특성을 기반으로하는 몇 가지 제품이 있습니다. 범주에서 각 제품은 각 속성 옵션에 대한 값을 선택했을 것입니다. 두 속성 (Manufacturer, Mobile Network)이있는 경우 각 제품은 deal_id, attribute_id 및 th를 연결하는 deal_attribute_values의 값을 갖습니다 선택 가치 (그래서 제품은 Samsung 제조자와 Vodafone으로 서비스 제공자가 될 수 있습니다).

지금 수행하려는 작업은 검색 쿼리를 기반으로하며 프런트 엔드 필터링을 기반으로 연결된 행을 반환합니다. 프론트 엔드의 폼이 변경되면 폼의 값을 직렬화하고 아약스를 통해 해당 쿼리를 기반으로 올바른 제품을 반환합니다.

나는 attribute_values를 제외하고는 완벽하게 작동하고 있습니다. 나는 그것이 질의 내 IN() 절과 관련이 있다고 의심하지만, 누군가 내가 잘못하고있는 것을 도와 줄 수 있기를 바랍니다.여기

이 모델 방법 :

여기
public function getDeals() { 

    $select = array(); 
    $tables = array(); 
    $where = array(); 
    $values = array(); 

    // Default to get all deal rows: 
    $select[] = "`deals`.*"; 
    $tables[] = "`deals`"; 

    // Get the category Name AND ID 
    $select[] = "`deal_categories`.`name` AS `catName`"; 
    $tables[] = "`deal_categories`"; 
    $where[] = "`deals`.`deal_category_id`=`deal_categories`.`id`"; 

    // Look if a category was selected: 
    $cat = $_POST['category']; 
    if ($cat != "") { 
     $where[] = "`deals`.`deal_category_id`=?"; 
     $values[] = $cat; 
    } 

    // Assign a query of the deal by string: 
    if ($_POST['searchDeals'] != "") { 
     $where[] = "CONCAT_WS(' ',`deals`.`name`,`deals`.`description`) LIKE ?"; 
     $values[] = "%" . str_replace(" ", "%", htmlspecialchars($_POST['searchDeals'])) . "%"; 
    } 

    // Process Min/Max PRicing: 
    if (isset($_POST['minPrice'])) { 
     $minPrice = intval($_POST['minPrice']); 
     $where[] = "`deals`.`price` >= ?"; 
     $values[] = $minPrice; 
    } 

    if (isset($_POST['maxPrice'])) { 
     $maxPrice = intval($_POST['maxPrice']); 
     $where[] = "`deals`.`price` <= ?"; 
     $values[] = $maxPrice; 
    } 

    // PRocess the min/max dates: 
    if (isset($_POST['minDate'])) { 
     $minDate = $_POST['minDate']; 
     $where[] = "`deals`.`start_date` >= ?"; 
     $values[] = $minDate; 
    } 

    if (isset($_POST['maxDate'])) { 
     $maxDate = $_POST['maxDate']; 
     $where[] = "`deals`.`end_date` <= ?"; 
     $values[] = $maxDate; 
    } 

    if (isset($_POST['attr']) && valid_array($_POST['attr'])) { 
     $tables[] = "`deal_attribute_values`"; 
     foreach ($_POST['attr'] AS $attrID => $checked) { 
      $values[] = $attrID; 
      $where_condition = "`deals`.`id`=`deal_attribute_values`.`deal_id` 
     AND `deal_attribute_values`.`deal_attribute_id`=? 
     AND `deal_attribute_values`.`value` IN ("; 
      $bind_placeholder = array(); 
      foreach ($checked as $val) { 
       $bind_placeholder[] = "?"; 
       $values[] = $val; 
      } 
      $where_condition .= implode(',', $bind_placeholder) . ")"; 
      $where[] = $where_condition; 
     } 
    } 

    $sql = "SELECT " . implode(", ", $select) . " FROM " . implode(",", $tables) . " WHERE " . implode(" AND ", $where); 

    return $this->get($sql, $values); 
} 

는 속성을 포함한 샘플 POST이다 (참고 키 3, 4) 속성 콜렉션 (제조업체 및 서비스 제공 업체)을 나타냅니다. 이 값들은 IN()이 작동하기를 원하는 점검 된 옵션입니다. PDO의 값을 여기

SELECT `deals`.*, `deal_categories`.`name` AS `catName` FROM `deals`,`deal_categories`,`deal_attribute_values` WHERE `deals`.`deal_category_id`=`deal_categories`.`id` AND `deals`.`deal_category_id`=? AND `deals`.`price` >= ? AND `deals`.`price` <= ? AND `deals`.`start_date` >= ? AND `deals`.`end_date` <= ? AND `deals`.`id`=`deal_attribute_values`.`deal_id` AND `deal_attribute_values`.`deal_attribute_id`=? AND `deal_attribute_values`.`value` IN (?,?,?,?) AND `deals`.`id`=`deal_attribute_values`.`deal_id` AND `deal_attribute_values`.`deal_attribute_id`=? AND `deal_attribute_values`.`value` IN (?,?,?) 

그리고입니다 : 여기

Array 
(
[searchDeals] => 
[category] => 2 
[attr] => Array 
    (
     [3] => Array 
      (
       [0] => 8 
       [1] => 9 
       [2] => 12 
       [3] => 10 
      ) 

     [4] => Array 
      (
       [0] => 4 
       [1] => 7 
       [2] => 5 
      ) 

    ) 

[minPrice] => 100000 
[maxPrice] => 9500 
[minDate] => 2014-10-26 00:00:00 
[maxDate] => 2014-11-30 00:00:00 
) 

위 (업데이트 코드 업데이트 기준)에 따라 SQL을 출력

Array 
(
[0] => 2 
[1] => 100000 
[2] => 9500 
[3] => 2014-10-26 00:00:00 
[4] => 2014-11-30 00:00:00 
[5] => 3 
[6] => 8 
[7] => 9 
[8] => 12 
[9] => 10 
[10] => 4 
[11] => 4 
[12] => 7 
[13] => 5 
) 

나는 것을 확인할 수 있습니다 특성이 도입 될 때까지 결과가 나타납니다. 나는 모든 atttributes를 untick (manufactuer와 서비스 제공자 둘 모두를위한)하고 단지 하나의 속성을 선택하는 "Apple"이 하나의 제품을 반환한다고 말하면서 여전히 결과를 얻을 수 있지만 관련 서비스 제공자를 선택하면 결과.

기본적으로 특성을 사용하여 attribute_values ​​테이블 내의 해당 제품 값이 IN() 절의 특성 내에 있으면 행을 선택하고 싶습니다. 카테고리를 기반으로하는 여러 속성이 있으므로 Apple, Samsung 및 Vodacom/MTN을 SP로 유지하면 여러 제품을 반환해야합니다. 제품이 samsung이고 반환해야하는 Vodacom/MTN 인 경우 또는 제조사를 선택하지 않고 Vodacom/MTN 만 SP로 선택하면 MTN/Vodacom 인 모든 핸드셋을 반환해야합니다. Vodacom이없는 경우에도 모든 MTN을 반환해야합니다.

추가 도움/정보가 필요하면 알려주십시오. 그래서 모든 사람들이 이해를 바랍니다 :) 여기에 많은 세부 사항을 가지고 노력

** 답변의 UPDATE **

내 말에 작동 알렉스에 의해 게시 코드 2 명 변경했습니다! 난 당신이 문제가 IN 절에 있다는 사실에 대한 맞아 믿고 당신에게 알렉스 :

if (isset($_POST['attr']) && valid_array($_POST['attr'])) { 
     foreach ($_POST['attr'] AS $attrID => $checked) { 
      $current_table = "`deal_attribute_values` AS `dav" . $attrID."`"; 
      $asName = "`dav".$attrID."`"; 
      $values[] = $attrID; 
      $where_condition = "`deals`.`id`=".$asName.".`deal_id` 
     AND " . $asName . ".`deal_attribute_id`=? 
     AND " . $asName . ".`value` IN ("; 
      $bind_placeholder = array(); 
      foreach ($checked as $val) { 
       $bind_placeholder[] = "?"; 
       $values[] = $val; 
      } 
      $where_condition .= implode(',', $bind_placeholder) . ")"; 
      $where[] = $where_condition; 
      $tables[] = $current_table; 
     } 
    } 
+0

첫째, 매우 상세한 질문 :

그리고 그것은처럼 whould이 필요한 코드를 변경합니다 ($tables[] 부분에 대한 변경 사항을 참조)

. +1. – itachi

답변

1

감사드립니다. 준비된 문과 IN 절에 대한 값을 제공하는 데 문제가 있습니다. IN 절 조건을 하나의 매개 변수로 전달할 수 없으므로 자동으로 개별 값이 아닌 전체를 이스케이프 처리합니다.

그래서 당신은 :

if (isset($_POST['attr']) && valid_array($_POST['attr'])) { 
    $tables[] = "`deal_attribute_values`"; 
    foreach ($_POST['attr'] AS $attrID => $checked) { 
     $str = implode(", ", $checked); 
     $where[] = "`deals`.`id`=`deal_attribute_values`.`deal_id` 
     AND `deal_attribute_values`.`deal_attribute_id`=? 
     AND `deal_attribute_values`.`value` IN (?)"; 
     $values[] = $attrID; 
     $values[] = $str; 
    } 
} 

당신이 문에 $str 매개 변수를 바인딩 할 때 따라서 IN 대신 쉼표로 구분 된 값의 하나의 값을 갖는 따옴표로 전체 $str를 캡슐화합니다.당신과 같이 원하는

  1. 당신은 그것을
  2. 당신은 IN 값 각각에 대해 IN 절에 충분한 ?를 추가 결합하지 않고 쿼리에 $str를 추가 중 :

    당신은 두 가지 옵션이 있습니다

 
    foreach ($_POST['attr'] AS $attrID => $checked) { 
      $values[] = $attrID; 
      $where_condition = "`deals`.`id`=`deal_attribute_values`.`deal_id` 
      AND `deal_attribute_values`.`deal_attribute_id`=? 
      AND `deal_attribute_values`.`value` IN ("; 
      $bind_placeholder = array(); 
      foreach($checked as $val) { 
        $bind_placeholder[] = "?"; 
        $values[] = $val; 
      } 
      $where_condition .= implode(',', $bind_placeholder).")"; 
      $where[] = $where_condition; 
     } 

위로 대답 : 논리 오류가 있습니다. 당신의 질문. 속성 카테고리를 1 개 이상 도입하면 deal_attribute_values.deal_attribute_id=? 조건이 두 번 나타납니다. 즉, 동일한 행에 대해 deal_attribute_id이 동시에 2 개의 값과 같아야 함을 의미합니다.

쿼리를 수정해야 쿼리에 추가 할 각 속성 범주/세트에 대해 deal_attribute_values을 조인 목록에 추가해야합니다. 내가이 너무 속성의 두 번째 그룹을 일치시키기 위해입니다 dav2deal_attribute_values을 추가 한

SELECT deals.*, deal_categories.name AS catName FROM deals,deal_categories,deal_attribute_values, deal_attribute_values AS dav2 WHERE deals.deal_category_id=deal_categories.id AND deals.deal_category_id=? AND deals.price >= ? AND deals.price <= ? AND deals.start_date >= ? AND deals.end_date <= ? AND deals.id=deal_attribute_values.deal_id AND deal_ attribute_values.deal_attribute_id=? AND deal_attribute_values.value IN (?,?,?,?) AND deals.id=dav2.deal_id AND dav2.deal_attribute_id=? AND dav2.value IN (?,?,?)

주의 : 그래서 마지막 업데이트 쿼리는 다음과 같이 보일 것입니다. 모든

 
    if (isset($_POST['attr']) && valid_array($_POST['attr'])) { 
     foreach ($_POST['attr'] AS $attrID => $checked) { 
      current_table = "`deal_attribute_values` AS dav".$attrID; 
      $values[] = $attrID; 
      $where_condition = "`deals`.`id`=`".$current_table."`.`deal_id` 
      AND `".$current_table."`.`deal_attribute_id`=? 
      AND `".$current_table."`.`value` IN ("; 
      $bind_placeholder = array(); 
      foreach($checked as $val) { 
        $bind_placeholder[] = "?"; 
        $values[] = $val; 
      } 
      $where_condition .= implode(',', $bind_placeholder).")"; 
      $where[] = $where_condition; 
      $tables[] = $current_table; 
     } 
    } 
+0

이것은 "거의"트릭을 완료했습니다! 돌아 오는 즉시 "Manufacturer"와 "Provider"가 모두 체크 된 경우 적절한 휴대폰을 보여줍니다. 제조사 중 어느 쪽이라도 나갈 때가되면 모두 다시 털어 버릴지라도. 내가 모든 공급자를 말하고 모든 manufactuers 똑딱 똑딱 떠날 경우, 이것은 완벽하게 작동하지만, 내가 공급자를 추가하는 순간 (심지어는 정확하게 일치하거나 모든 제공자에게 똑딱 거리지 만) 어떤 결과도 얻지 못합니다. 두 속성을 동시에 실행할 수없는 것처럼 amost입니다 (하나는 IN() 또는 제공자의 IN()을 실행합니다.) 어떤 아이디어입니까? – mauzilla

+0

해당 값이 바인드되어 있습니까? 두 가지 옵션 중 어느 것을 사용하고 있습니까? – AlexL

+0

이 경우 카테고리 (휴대 전화)에는 2 개의 속성 (공급자, 제조업체)이 있습니다. 제품이 생성되면 속성도 예제와 같이 선택됩니다 제품은 삼성과보다 폰을 공급자로 사용할 수 있습니다. 프런트 엔드에서는 모든 가능한 공급자와 모든 가능한 제조업체를 반환하고 확인란을 기반으로 모든 공급자와 제조업체 중 일부와 함께 모든 제품을 필터링하고 찾아야합니다. 제품에는 제조업체 및 제공 업체가 있으므로 사용자가 제조업체로 삼성을 선택하고 모든 제공 업체를 확인한 상태로두면 여전히 반환해야합니다. 도움이 되나요? – mauzilla

관련 문제