2012-07-31 3 views
2

이렇게 코드를 작성하고 너무 많은 쿼리를 수행하지 않아도 똑같은 작업을 수행 할 수있는 간단한 방법이 있습니까? 내가 페이지 매김 (여기 코드에 포함되지 않음)을 추가하려하고 내 모든 쿼리에서 작동하지만 AND/OR 쿼리가 재미있는 결과를 내고 두통이되고 있습니다. 그 외 결과 필터링은 완벽하게 페이지 매김이 필요합니다.PDO 다중 필터 SQL 쿼리

$filter = isset($_POST['filter']) ? $_POST['filter'] : null; 
$status = isset($_POST['status']) ? $_POST['status'] : null; 

if(empty($filter) && empty($status)) { 

    //echo 'ALL query'; 
    $sql = 'SELECT * FROM _product JOIN _module_type ON module_type = module_id'; 
    $sth = $link->prepare($sql); 
    $sth->execute(array()); 
    $result = $sth->fetchall(); 

} else { 
    // display result if filter AND status are selected 
    if(!empty($filter) && !empty($status)) { 

     //echo 'AND query'; 
     $sql = 'SELECT * FROM _product JOIN _module_type ON module_type = module_id WHERE module_type = :filter AND product_status = :status'; 
     $sth = $link->prepare($sql); 
     $sth->execute(array(':filter' => $filter, ':status' => $status)); 
     $result = $sth->fetchall(); 

    } else { 
     // display result if filter OR status are selected 
     if(!empty($filter) || !empty($status)) { 

      //echo 'OR query'; 
      $sql = 'SELECT * FROM _product JOIN _module_type ON module_type = module_id WHERE module_type = :filter OR product_status = :status'; 
      $sth = $link->prepare($sql); 
      $sth->execute(array(':filter' => $filter, ':status' => $status)); 
      $result = $sth->fetchall(); 

     } 
    } 
} 

//test sql 
echo $sql.'<br />'; 

$bgcolor = ''; 
foreach($result as $key => $value) { 

    if(($bgcolor=='#ffffff') ? $bgcolor='#f1f1f1' : $bgcolor='#ffffff') { 

    echo '<tr bgcolor="'.$bgcolor.'">'; 
    echo '<td>'.$value['product_id'].'</td>'; 
    echo '<td>'.$value['product_name'].'</td>'; 
    echo '<td>'.$value['product_type'].'</td>'; 
    echo '<td>'.$value['module_name'].'</td>'; 
    echo '<td>'.$value['product_price'].'</td>'; 
    echo '<td>'.$value['product_status'].'</td>'; 
    echo '</tr>'; 
    } 
} 
    echo '</table>'; 
+1

의 한 줄을 변경할 필요가 없습니다 것입니다. 여기에 대한 답변을 참조하십시오 : http://stackoverflow.com/questions/11740066/simplify-a-mysql-query-that-can-have-multiple-input-options-using-php – Jim

답변

2

그리고 제 2의 생각 :

$sql = 'SELECT * FROM _product JOIN _module_type ON module_type = module_id WHERE'; 
if(!empty($filter) || !empty($status)){ 
    $sql .= ' module_type = :filter '.(!empty($filter) && !empty($status) ? 'AND' : 'OR').' product_status = :status'; 
    $sth = $link->prepare($sql); 
    $sth->bindValue(':filter', $filter); 
    $sth->bindValue(':status', $status); 
}else{ $sth = $link->prepare($sql); } 
$result = $sth->execute(); 

그것은 테스트를 필요로하고 진실은 당신이 OR하지만, 필요하지 않을 수도 있습니다 말했듯이 그 양식 및 필터링은 TBH 작동 정확히 개까지,하지만 난 거 휴가입니다 그것은 다음 단계로 이동할 수있는 포인터를 제공해야합니다. 다시

편집 :

$params = array(); 
$where = array(); 

if(!empty($filter)){ 
    $params[':filter'] = $filter; 
    $where[] = 'module_type = :filter'; 
} 
if(!empty($status)){ 
    $params[':status'] = $status; 
    $where[] = 'product_status = :status'; 
} 

$sql = 'SELECT * FROM _product JOIN _module_type ON module_type = module_id'.(sizeof($where) > 0 ? ' WHERE '.implode(' AND ', $where) : ''); 

$sth = $link->prepare($sql); 
foreach($params as $k=>$v) $sth->bindValue($k, $v); 
$result = $sth->execute(); 
+0

두 번째 예제를 시도해 보았습니다. "WHERE"는 SQL에 module_type 앞에 문자열을 연결하여 페이지로드시 모든 결과를 표시하는지 확인합니다. 나는 또한 sth를 꼬집었다. 지금은 잘 작동합니다. 이제 3 번째 예를 테스트 해 보겠습니다. – dynamo

+0

@dynamo 최신 편집을해야합니다. 원본 게시물에 문제가 있습니다. – Sammaye

1

내 생각이 $_POST 배열을 반복하고 당신이 필요로하는 변수 만 바인딩하는 것입니다

여기, 자신을 도울 수 없습니다 세 번째 가능성이다.

귀하는 AND 및 OR 사용에 대한 오해가 있습니다. 두 개 중 하나만 선택하면 두 번째를 OR 할 필요가 없습니다!

<?php 

    /** 
    * @param PDO $pdo  Database connection 
    * @param array $parameters Parameters (status, filter) 
    * 
    * @return array   The resultset returned from the query 
    */ 
    function select_product(\PDO $pdo, array $parameters = array()) { 
     $query = <<<MySQL 
SELECT * 
    FROM _product 
    JOIN _module_type 
    ON module_type = module_id 

MySQL; 
     if (!empty($parameters)) { 
      $query .= "WHERE "; 
      $where_clauses = array(); 
      foreach ($parameters as $param => $value) { 
       $where_clauses[] = "$param = :$param"; 
      } 
      $where_clauses = implode(" AND ", $where_clauses); 
      $query .= $where_clauses; 
     } 

     $stmt = $pdo->prepare($query); 
     foreach ($parameters as $param => $value) { 
      $stmt->bindValue(":$param", $value); 
     } 
     $stmt->execute(); 

     $results = $stmt->fetchAll(PDO::FETCH_ASSOC); 
     return $results; 
    } 

    try { 
     $db = new PDO("mysql:host=localhost;dbname=database_name", "user", "password"); 
     $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 
     $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
     select_product($db, $_POST); 
    } 
    catch (PDOException $e) { 
     die("Database problem occurred! " . $e->getMessage()); 
    } 

코드는 당신을 위해하지 일 그대로, 그래서 바로 그것을 복사/붙여 넣기하지 않는 것입니다.

이 함수는 양식 이름이 데이터베이스 이름과 일치한다고 가정하고 이에 따라 작동합니다. 열 이름이 module_type 인 경우 module_type과 일치하는 양식 필드의 이름을 지정하십시오.

이러한 코드의 장점은, 당신이 더 많은 열이 많은 필터를 추가 할 수 있습니다, 그리고 당신은 내가 오늘 아침에 비슷한 질문을했다 코드 :