高级搜索,PHP& MySQL的

时间:2012-03-28 06:02:16

标签: php mysql

我正在尝试创建一个类似于此的高级搜索表单;

http://img805.imageshack.us/img805/7162/30989114.jpg

但我应该为查询撰写什么?

我知道如果只有两个文本框而不是三个文本框怎么做,那么用户的概率太高了。

$query = "SELECT * FROM server WHERE ???";

我应该为“???”

写些什么

我知道如何在查询中使用AND OR,但是假设用户只填写两个文本框而一个空。如果我写这样的话;

$query = "SELECT * FROM server WHERE model='".$model."' and brand='".$brand."' and   SN='".$SN.'" ";

结果将作为空集返回。我希望用户可以选择是否填写一个,两个或三个标准。如果我使用OR,结果将不准确,因为如果Model有两个具有相同名称的数据(例如:M4000)但品牌不同(例如:IBM和SUN)。如果我使用OR并且用户想要搜索M4000和SUN,它将显示两个M4000。这就是为什么它不准确。

5 个答案:

答案 0 :(得分:4)

如果用户可以决定他想为搜索输入多少条件,并且您想要合并这些条件(只有那些实际由用户填写的条件),那么您必须动态创建SQL查询以仅包含那些字段。由用户填写的搜索。我给你举个例子。

简单搜索表单的代码可能如下所示:

$search_fields = Array(
    // field name => label
   'model'     => 'Model',
   'serialNum' => 'Serial Number',
   'brand'     => 'Brand Name'
);
echo "<form method=\"POST\">";
foreach ($search_fields as $field => $label) {
    echo "$label: <input name=\"search[$field]\"><br>";
}
echo "<input type=\"submit\">";
echo "</form>";

这样的实际搜索代码:

if (isset($_POST['search']) && is_array($_POST['search'])) {
    // escape against SQL injection
    $search = array_filter($_POST['search'], 'mysql_real_escape_string');
    // build SQL
    $search_parts = array();
    foreach ($search as $field => $value) {
        if ($value) {
            $search_parts[] = "$field LIKE '%$value%'";
        }
    }
    $sql = "SELECT * FROM table WHERE " . implode(' AND ', $search_parts);
    // do query here
}
else {
    echo "please enter some search criteria!";
}

在上面的代码中,我们动态构建SQL字符串,仅对输入的条件进行搜索(“AND”)。

答案 1 :(得分:1)

对于熟悉mysql的人,它提供了通过正则表达式(posix样式)进行搜索的功能。我需要一种在php中搜索的高级方法,而我的后端是mysql,所以这是合乎逻辑的选择。问题是,如何根据输入构建一个完整的mysql查询?以下是我希望能够处理的查询类型:

  1. 确切的字匹配
  2. 子字符串匹配(我这样做是像“%WORD%”)
  3. 通过子字符串匹配排除
  4. 通过精确的单词匹配排除
  5. 简单的正则表达式查询如下所示:

      

    从TABLE中选择*其中ROW regexp'[[:&lt;:]] bla [[:&gt;:]]'和ROW   regexp'foo';

    这将查找字符串“bla”的完全匹配,意味着不是作为子字符串,然后在某处匹配子字符串“foo”。

    首先,第1项和第4项是精确的单词匹配,我希望能够通过用引号括起来来实现这一点。让我们设置必要的变量然后匹配引号:

    $newq = $query; # $query is the raw query string
    $qlevel = 0;
    $curquery = "select * from TABLE where "; # the beginning of the query
    $doneg = 0;
    preg_match_all("/\"([^\"]*)\"/i", $query, $m);
    $c = count($m[0]);
    for ($i = 0; $i < $c; $i++) {
    $temp = $m[1][$i]; # $temp is whats inside the quotes
    

    然后我希望能够排除单词,并且用户应该能够通过用短划线( - )开始单词来实现这一点,并且对于精确的单词匹配,这必须在引号内。第二个匹配是在查询前摆脱 -

     if (ereg("^-", $temp)) {
              $pc = preg_match("/-([^-]*)/i", $m[1][$i], $dm);
              if ($pc) {
                   $temp = $dm[1];
                   }
              $doneg++;
              }
    

    现在我们将$ temp设置为与posix兼容的完全匹配,然后构建mysql查询的这一部分。

     $temp = "[[:<:]]".$temp."[[:>:]]";
     if ($qlevel) $curquery .= "and "; # are we nested?
     $curquery .= "ROW "; # the mysql row we are searching in
     if ($doneg) $curquery .= "not "; # if dash in front, do not
     $curquery .= "regexp ".quote_smart($temp)." ";
         $qlevel++;
     $doneg = 0;
     $newq = ereg_replace($m[0][$i], "", $newq);
     }
    

    变量$ newq具有搜索字符串的其余部分,减去引号中的所有内容,因此剩下的是子字符串搜索项目在2和3之下。现在我们可以通过剩下的内容并基本上做同样的事情。上方。

        $s = preg_split("/\s+/", $newq, -1, PREG_SPLIT_NO_EMPTY); #whitespaces
        for ($i = 0; $i < count($s); $i++) {
             if (ereg("^-", $s[$i])) { # exclude
                  sscanf($s[$i], "-%s", $temp); # this is poor
                  $s[$i] = $temp;
                  $doneg++;
                  }
             if ($qlevel) $curquery .= "and ";
             $curquery .= "ROW "; # the mysql row we are searching in
             if ($doneg) $curquery .= "not ";
             $curquery .= "regexp ".quote_smart($s[$i])." ";
             $qlevel++;
         $doneg = 0;
         }
    # use $curquery here in database
    

    变量$ curquery现在包含我们构建的mysql查询。你会注意到在这里使用quote_smart,这是来自php.net的mysql最佳实践。这是本代码中唯一提到的安全性。你需要针对输入运行自己的检查,以确保没有坏字符,我只允许使用字母数字和其他一些字符。如果没有先修复它,请不要使用此代码。

答案 2 :(得分:1)

试试此代码

<?php

$model="";
$brand="";
$serialNum="";

$model=mysql_real_escape_string($_POST['model']);
$brand=mysql_real_escape_string($_POST['brand']);
$serialNum=mysql_real_escape_string($_POST['serialNum']);

$query=" select * from server";
$where_str=" where ";

if($model == "" && $brand == "" && $serialNum == "")
{
  rtrim($where_str, " whrere "); 
}
else
{
   if($model != "")
   {
     $where_str.= "  model like '%$model%' AND ";
   }
   if($brand != "")
   {
     $where_str.= "  brand like '%$brand%' AND ";
   }
   if($serialNum != "")
   {
     $where_str.= "  serialNum like '%$serialNum%' AND ";
   }

rtrim($where_str, " AND ");
}

$query.= $where_str;
$records=mysql_query($query);
?>

答案 3 :(得分:0)

您必须提供来自搜索表单的$ model,$ brand,$ serial。

$query = "SELECT * FROM `TABLE` WHERE `model` LIKE '%$model%' AND `brand` LIKE '%$brand%' AND `serial` LIKE '%$serial%'";

另外看一下mysql doc

http://dev.mysql.com/doc/refman/5.1/en/string-comparison-functions.html

答案 4 :(得分:0)

基本搜索可以这样工作:

  

“SELECT * FROM server WHERE column_name1 LIKE'%keyword1%'AND column_name2 LIKE'%keyword2%'.....”;

这是匹配所有参数的情况。为匹配任何一个条件,将AND更改为OR