使用变量选项构建 PHP/MySQL 搜索查询

Constructing PHP/MySQL search query with variable options

本问题已经有最佳答案,请猛点这里访问。

我想做什么

我有一个 SQL 表,其中包含客户网站的工作机会列表。

我正在尝试创建一个搜索表单,但并非必须填写所有字段。

可能的值是:

title = 工作标题

location = 作业位置

sal1 = 所需薪水的底部括号

sal2 = 期望薪水的上括号

代码

1
2
3
4
5
6
7
8
9
$query = 'SELECT * FROM `jobs`';

if($_GET['title']!='') $query.= ' AND `title` LIKE %'.$_GET['title'];
if($_GET['location']!='') $query.= ' AND `location`='.$_GET['location'];
if($_GET['sal1']!='') $query.= ' AND `sal1`>='.$_GET['sal1'];
if($_GET['sal2']!='') $query.= ' AND `sal2`<='.$_GET['sal2'];

$stmt=$dbh->prepare($query.' ORDER BY `date` DESC');
$stmt->execute();

问题

理论上这种方法应该有效,但我更喜欢使用准备好的语句。这样做的唯一方法似乎是在每个 $_GET 变量上使用 mysql_real_escape_string(),因为当我不知道使用了多少变量时,我无法弄清楚如何使用 execute(array($val1,$val2...))

如果可能,我如何利用准备好的语句来清理 $_GET 变量?


您可以向 execute() 传递一个关联数组。您只需为 $_GET 中的每个值添加占位符,然后将整个数组传递给 execute()

所以,首先你创建你的查询字符串,准备它,然后调用 execute().

附言你忘记了 WHERE。没有 WHERE 就不能使用 AND。我建议像这样构建查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// Base query
$query = 'SELECT * FROM `jobs`';

// WHERE clauses
$where = array();

// Don't concat GET values, use placeholders
if($_GET['title'] != '') $where[] = '`title` LIKE CONCAT("%", :title)';
if($_GET['location'] != '') $where[] = '`location` = :location';
if($_GET['sal1'] != '') $where[] = '`sal1`>= :sal1';
if($_GET['sal2'] != '') $where[] = '`sal2`<= :sal2';

// Combine the WHERE clauses
if(count($where) > 0) $query .=" WHERE".implode(' AND ', $where);

// Prepare the query
$stmt = $dbh->prepare($query.' ORDER BY `date` DESC');

// Run it with the entered parameters
$stmt->execute($_GET);

注意:我在第一个子句中做 CONCAT("%", :title)。这是因为 LIKE 需要一个字符串。它需要类似 '%test' 的东西(注意 % 是字符串的一部分)。我在 MySQL 中使用 CONCAT 而不是在 PHP 中使用 $_GET['title'] = '%'.$_GET['title'];


代替冗长且容易出错的连接,填充两个数组 - placeholders 和 params - 在你进行时,并在最后一次插入所有占位符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$where  = array();
$params = array();

if(!empty($_GET['title'])) {
    $where  []= '`title` LIKE ?';
    $params []= '%' . $_GET['title'];
}

if(!empty($_GET['location'])) {
    $where  []= '`location` = ?';
    $params []= $_GET['location'];
}

// etc

if(!count($where))
    // error

$where = implode(' AND ', $where);
$query ="SELECT * FROM `jobs` WHERE $where ORDER BY `date` DESC";

$stmt=$dbh->prepare($query);
$stmt->execute($params);


您可以使用 bindParam:

处理可变数量的查询参数

Binds a PHP variable to a corresponding named or question mark placeholder in the SQL statement that was used to prepare the statement.

文档在这里。

编辑
使用 LIKE:如何使用 LIKE 语句创建 PDO 参数化查询?