【问题标题】:Constructing PHP/MySQL search query with variable options [duplicate]使用变量选项构建 PHP/MySQL 搜索查询 [重复]
【发布时间】: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,除非这只是您实际代码的一部分(?)。

标签: php mysql


【解决方案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.

编辑 使用LIKEHow 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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 2011-11-05
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    相关资源
    最近更新 更多