【问题标题】:Refining the search results based on the filters根据过滤器优化搜索结果
【发布时间】:2011-10-12 00:44:46
【问题描述】:

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

  1. 品牌名称

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

    • $100-$200
    • $200-$300
    • (等等)
  3. 类别

    • Android 手机
    • 低成本手机
    • 音乐手机
    • 3G 手机
    • ...(还有更多)

我想使用以下 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比我上面说的方法好?

我在 Windows 机器上使用 PHP、MySQL、Apache。

【问题讨论】:

    标签: php mysql web-applications search


    【解决方案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
    

    【讨论】:

    • 对于第一个问题:使用$url 变量设置URL 后,我应该将新标准(价格)附加到URL...对吗??如果是,那么如何将用户重定向到$url
    • @iSummitG 是的,您应该附加新标准..我只是向您展示粗略的想法并使用 header() 重定向用户
    • @slieer 非常感谢您的回答。我不能使用 isset($_GET('brand')) 而不是存储 SESSION 变量吗?如果设置了brand,那么我可以相应地附加新的过滤器,如果没有,那么我将使用唯一的新标准。如果我错了,请纠正我!
    • @iSummitG 我不知道您的搜索表单的详细实现。如果每个请求都存在 $_GET['brand'],只需使用它..为什么要打扰会话
    【解决方案2】:

    我很想构建一个调度表,为每个查询参数调用一个函数。这允许您创建安全查询参数的白名单。我还将使用参数化语句来帮助防止 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...
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-18
      • 2014-10-12
      • 1970-01-01
      • 2013-11-18
      • 2015-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多