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


Constructing PHP/MySQL search query with variable options

我想做什么

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

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

可能的值为:

title = 职位名称

location = 作业的位置

sal1 = 所需薪水的底部括号

sal2 = 所需薪水的最高括号

《守则》

$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。 我建议像这样构建查询:

// 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'];

您可以使用bindParam处理可变数量的查询参数:

将 PHP 变量绑定到用于准备语句的 SQL 语句中的相应命名或问号占位符。

文档在这里。

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

不要连接,这是冗长且容易出错的,而是随时填充两个数组 - 占位符和参数 - 并在末尾一次插入所有占位符:

$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);