使用变量选项构建 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->prepare($query);
),最后绑定 (if($_GET['location']!='') $stmt->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 搜索查询 [重复]的主要内容,如果未能解决你的问题,请参考以下文章
通过 Bootstrap Modals PHP MySQL 创建搜索记录表单