PDO多过滤器sql查询


PDO multi-Filter sql query

有没有一种更简单的方法可以让我在不需要那么多查询的情况下编写代码并执行同样的事情?我试图添加分页(这里的代码中不包括),它适用于我的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数组,只绑定所需的变量。

你误解了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

这样的代码的优点是,您可以添加更多的列和更多的过滤器,并且不必更改一行代码:)