【问题标题】:Generating SQL query based on URL parameters根据 URL 参数生成 SQL 查询
【发布时间】:2011-08-03 02:39:47
【问题描述】:

假设我的网址是http://something.com/products.php?brand=samsung&condition=new

对于上述查询,我​​使用isset()$_GET[]) 函数以及PHP 中的大量if-else 语句来生成用于显示满足搜索条件的产品的sql 查询。

例如:如果我只处理 brandcondition 参数,那么这就是我生成查询的方式:

$sql = "select * from products where 1=1 ";
if(isset($_GET['brand']))
{
     if(isset($_GET['condition']))
     {
         $sql = $sql + "and brand=".$_GET['brand']." and condition=".$_GET['condition'];
     }
}
else
{
     if(isset($_GET['condition']))
     {
         $sql = $sql + "and condition=".$_GET['condition'];
     }
     else
     {
         $sql = $sql + ";";
     }
}

现在假设我的网址有 10 个(或更多)参数。在这种情况下,使用if-else 一点都不好。如何在不使用这么多 if-else 语句的情况下生成查询?有没有更好的方法/脚本/库来做这件事?

【问题讨论】:

    标签: php javascript mysql web-services


    【解决方案1】:

    有很多方法可以做到这一点,但最简单的方法是遍历可接受的列,然后适当地追加。

    // I generally use array and implode to do list concatenations. It avoids
    // the need for a test condition and concatenation. It is debatable as to
    // whether this is a faster design, but it is easier and chances are you 
    // won't really need to optimize that much over a database table (a table
    // with over 10 columns generally needs to be re-thought)
    $search = array();
    // you want to white-list here. It is safer and it is more likely to prevent
    // destructive user error.
    $valid  = array( 'condition', 'brand' /* and so on */ );
    
    
    foreach( $valid as $column )
    {
       // does the key exist?
       if( isset( $_GET[ $column ] ) )
       {
          // add it to the search array.
          $search[] = $column . ' = ' . mysql_real_escape_string( $_GET[ $column ] );
       }
    }
    $sql = 'SELECT * FROM TABLE_NAME WHERE ' . implode( ' AND ', $search );
    // run your search.
    

    如果你真的想摆脱'if'语句,你可以使用这个:

    $columns = array_intersect( $valid, array_keys( $_GET ) );
    foreach( $columns as $column )
    {
        $search[] = $column . ' = ' . mysql_real_escape_string( $_GET[ $column ] );
    }
    $sql = 'SELECT * FROM TABLE_NAME WHERE ' . implode( ' AND ', $search );
    

    但您可能需要运行实际的基准测试以确定这是否是一个更好的选择。

    【讨论】:

    • 感谢您的回答。但你的回答会执行与我的代码相同数量的if-else 语句,这会在服务器上产生大量负载。
    • @iSumitG 与其他一切相比,像这样的 if/else 语句真的快。例如,比数据库查询快 数千倍 倍。这里的问题真的应该是“我如何使这段代码更具可读性/可重用性?”而不是更快。如果您认为这很重要,请对两者的性能进行基准测试,看看是否有显着差异。
    • @iSumitG 实际上,从外观上看,您的代码将产生 O(n^2) if/else 条件。我的只会产生 O(n) 条件,其中 n = 白名单中的列数(这是非常理想的)。我添加了一个辅助块以允许您删除if 的实际使用,但这仍然是 O(n)(不同之处在于 n 是较小的数组的值)。但是,由于创建 Array 需要时间,我不确定使用 array_diff + array_keys 是否真的会比原始白名单节省那么多时间。您需要进行基准测试。
    猜你喜欢
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    • 2011-09-17
    • 1970-01-01
    相关资源
    最近更新 更多