使用变量选项构建 PHP/MySQL 搜索查询 [重复]

Posted

技术标签:

【中文标题】使用变量选项构建 PHP/MySQL 搜索查询 [重复]【英文标题】:Constructing PHP/MySQL search query with variable options [duplicate] 【发布时间】:2015-01-21 16:29:39 【问题描述】:

我要做什么

我有一个 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 变量?

【问题讨论】:

% 在引号内。另外,您应该将所有$query.= 更改为$query .=,因为这会破坏您的查询。 @Fred-ii- “另外,您应该将所有 $query.= 更改为 $query .= 因为这会破坏您的查询。” whatchoo talkin bout?跨度> @Madbreaks 自己尝试一下。我不需要,我知道。 $query.= 尝试执行连接,$query .=(带有空格)正确地使用了操作数 @Madbreaks 但是,您拥有的 Ben 的代码似乎缺少一些东西。您现在的查询将转换为SELECT * FROM table AND column LIKE xxx ORDER BY,除非这只是您实际代码的一部分(?)。 【参考方案1】:

您可以传递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' 之类的东西(注意% 是字符串的part)。我在 MySQL 中使用 CONCAT 而不是在 php 中使用 $_GET['title'] = '%'.$_GET['title'];

【讨论】:

有些人似乎不同意我对$query.= 的评论,而有些人则同意。 $query.= 不会正确连接,“你”会同意吗?我以前见过因为没有正确连接而导致 OP 代码失败的地方 $query .= @Fred-ii-:在这里工作正常:eval.in/245783 好吧,我要做猴子叔叔。这太离奇了。正如我所说,几周前有一个问题,连接失败是因为之间没有空格。太诡异了。但是你为什么选择$query .=在你的回答中呢? @Fred-ii-:是的。 % 应该是字符串的一部分,而不是在字符串之外。【参考方案2】:

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

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

文档here.

编辑 使用LIKE:How do I create a PDO parameterized query with a LIKE statement?

【讨论】:

方法我很熟悉。我可以在不存在的变量上使用bindParam(即,如果用户没有搜索标题,通过将值绑定到:title 参数,它仍然可以正确搜索)吗? 你为什么要这样做?这个想法是,如果用户没有按标题搜索(例如 $_GET['title']; 为空),则不要绑定该参数,也不要将其包含在查询中。 我明白你的意思 - 扩展查询 (if($_GET['location']!='') $query .= ' AND location=:location';),然后准备 ($stmt=$dbh-&gt;prepare($query);),最后绑定 (if($_GET['location']!='') $stmt-&gt;bindParam(':location',$_GET['location']);),然后再执行工作。但是,通配符 :title 无法正常工作。在PDO语句中使用LIKE%的正确方法是什么? 我更新了答案。【参考方案3】:

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

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

【讨论】:

以上是关于使用变量选项构建 PHP/MySQL 搜索查询 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

PHP MYSQL 动态选择框

通过 Bootstrap Modals PHP MySQL 创建搜索记录表单

php + mysql - 性能 - 即时自动完成响应

使用 PHP/MySQL 自动化电子邮件活动,不确定如何构建查询

PHP MySQL:搜索查询仅适用于现有的完整术语

带有多个单词的PHP Mysql搜索查询