PDO с несколькими фильтрами sql-запроса

Есть ли более простой способ для меня кодировать это и выполнять одно и то же, не имея столько запросов? Я пытаюсь добавить разбиение на страницы (здесь не входит в код), и он работает над моим запросом ALL, но запросы AND / OR дают смешные результаты и становятся головной болью. Кроме того, фильтрация результатов работает идеально, просто нужно разбиение на страницы.

$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>'; 

И Моя вторая мысль:

 $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(); 

Моя мысль состоит в том, чтобы $_POST массив $_POST и привязать только нужные вам переменные.

Вы неправильно понимаете использование AND и 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 .

Преимущества такого кода в том, что вы можете добавить больше столбцов и больше фильтров, и вам не придется менять одну строку кода 🙂