根据过滤器优化搜索结果

时间:2011-07-24 13:26:47

标签: php mysql web-applications search

我正在开发一个电子商务网站。在显示可用的手机时,用户可以通过以下过滤器过滤结果:

  1. 品牌名称

    • 三星
    • 诺基亚
    • HTC
    • (还有更多)
  2. 价格范围

    • $ 100- $ 200
    • $ 200- $ 300
    • (依此类推)
  3. 分类

    • Android手机
    • 低成本手机
    • 音乐手机
    • 3G手机
    • ...(以及更多)
  4. 我想使用以下GET参数生成一个sql查询,该查询将在每次应用过滤器时执行。假设当前过滤器为Brand=Samsung,那么我的链接将为http://xyz.com/mobiles.php?brand=samsung

    对于上述过滤器,用于生成SQL查询的PHP代码如下(使用大量if/else语句和isset()函数):

    $sql = "SELECT * from items ";
    if(isset($_GET['brand']))
    {
         $sql = $sql . "where brand=".$_GET['brand']." ";
    /*similar statements*/
    }
    

    请不要继续上述PHP语句的准确性,我没有提到完整的代码。最后,我生成了以下SQL,它将提供结果:

    SELECT * FROM ITEMS 
    WHERE 
         BRAND=SAMSUNG;
    

    此SQL查询将生成匹配的产品,我将相应地在网页上显示结果。请回答以下问题:

    1. 在上述过滤器(品牌)之后,假设也应用价格过滤器。怎么样 我可以知道brand过滤器已经存在 我可以将用户重定向到

      http://xyz.com/mobiles.php?brand=samsung&priceMin=100&priceMax=200

      以下网址

      http://xyz.com/mobiles.php?priceMin=100&priceMax=200

      即。我怎样才能将价格标准附加到网址?

    2. 是否有可用于过滤产品的软件/库/代码?

    3. 有没有更好的方法来过滤产品或更好的方法 生成SQL而不是我上面提到的方法?

    4. 我在Windows机器上使用PHP,MySQL,Apache。

2 个答案:

答案 0 :(得分:1)

让我试着回答你的问题

1.如果用户已经过滤特定品牌,只需将品牌保存在会话变量

$sql = "SELECT * from items ";
if(isset($_GET['brand']))
{
    $_SESSION['brand'] = $_GET['brand'];
    //your code 
}

然后在下一个请求中检查是否存在该变量

if($_SESSION['brand'])
{
    $url = $_SERVER['PHP_SELF'] . '?brand=' . $_SESSION['brand'];
    header( 'Location:' . $url );
    exit;
}

2.我没有意识到..

3.您可以通过添加WHERE 1=1

来构建更好的查询
$query = "SELECT * FROM items WHERE 1=1";

if($_GET['brand')
{
    $query .= " AND brand={$_GET['brand'}";
}

//another condition perhaps

答案 1 :(得分:1)

我很想建立一个调度表,为每个查询参数调用一个函数。这允许您创建安全查询参数的白名单。我还将使用参数化语句来防止SQL注入(现有代码未受到保护)。 PDO使参数化语句变得容易。

首先为每个查询参数创建一个单独的函数似乎没必要,但这意味着您可以将所有条件放在一个单独的文件中,从而保持主查询功能整洁。它还使未来的增强功能更容易实现。

以下是一个非常粗略的例子。它并不意味着准备剪切并粘贴到应用程序中。这只是为了让你了解我的意思。在一个真实的应用程序中,您需要包含错误检查,并可能将数据库连接内容移动到其他位置。

// ** query_params.php **

function query_brand () {
    return "brand = ?";
}

function query_price () {
    return "price BETWEEN ? AND ?";
}

function query_category () {
    return "category = ?";
}

// ** product_search.php **

function search () {

    // Build a test GET array.
    $_GET = array(
        'brand'    => 'HTC',
        'price'    => array(100, 200),
        'category' => 'Android Mobiles'
    );

    // Build a dispatch table of safe query parameters.
    $dispatch = array(
        'brand'    => 'query_brand',
        'price'    => 'query_price',
        'category' => 'query_category'
    );

    // An array to hold the conditions.
    $cond = array();

    // An array to hold the bind values.
    $bind = array();

    foreach ( $_GET as $param => $value ) {
        if( isset($dispatch[$param]) ) {
            $cond[] = call_user_func( $dispatch[$param] );
            $bind[] = $value;
        }
    }

    $sql = "SELECT item, brand, price, category " .
           "FROM products";

    if( count($cond) ) {
        // Combine the conditions into a string.
        $where = implode( ' OR ', $cond );
        $sql .= " WHERE $where";
    }

    // Use PDO to connect to the database.  This should
    // probably be done somewhere else.
    $dbh = new PDO(
        "mysql:host=localhost;dbname=$dbname", $user, $pass,
    );

    // Prepare the SQL statement.
    $stmt = $dbh->prepare( $sql );

    // Execute the statement, passing the values to be
    // bound to the parameter placeholders.
    $stmt->execute( $bind );

    // Fetch and return results...
}