5

我想执行参数化查询以按用户提供的参数执行搜索。有很多参数,并不是所有的参数都会一直提供。如何进行标准查询来指定所有可能的参数,但如果用户没有选择有意义的参数值,则忽略其中一些参数?

这是一个假想的例子来说明我要做什么

$sql = 'SELECT * FROM people WHERE first_name = :first_name AND last_name = :last_name AND age = :age AND sex = :sex';
$query = $db->prepare($sql);
$query->execute(array(':first_name' => 'John', ':age' => '27');

显然,这是行不通的,因为提供的参数数量与预期参数的数量不匹配。我是否必须每次都只在 WHERE 子句中包含指定的参数来制作查询,或者有没有办法让其中一些参数被忽略或在检查时总是返回 true?

4

4 回答 4

8
SELECT * FROM people 
WHERE (first_name = :first_name or :first_name is null)
AND (last_name = :last_name or :last_name is null)
AND (age = :age or :age is null)
AND (sex = :sex or :sex is null)

传递参数时,提供null您不需要的参数。

请注意,为了能够以这种方式运行查询,emulation mode必须打开 PDOON

于 2012-06-27T17:12:21.853 回答
2

首先,首先将您的$sql字符串更改为:

$sql = 'SELECT * FROM people WHERE 1 = 1';

WHERE 1 = 1将允许您不包含任何其他参数...

接下来,有选择地将$sql任何具有有意义值的附加参数连接到您的字符串:

$sql .= ' AND first_name = :first_name'
$sql .= ' AND age = :age'

您的$sql字符串现在只包含您计划提供的参数,因此您可以像以前一样继续:

$query = $db->prepare($sql);
$query->execute(array(':first_name' => 'John', ':age' => '27');
于 2012-06-27T17:17:11.647 回答
1

如果您无法通过更改查询来解决问题...有几个库可以帮助组装查询。我过去使用Zend_Db_Select过,但每个框架都可能有类似的东西:

$select = new Zend_Db_Select;

$select->from('people');

if (!empty($lastName)) {
  $select->where('lastname = ?', $lastname);
}

$select->order('lastname desc')->limit(10);

echo $select; // SELECT * FROM people WHERE lastname = '...' ORDER BY lastname desc LIMIT 10
于 2012-06-27T17:14:09.807 回答
0

我已经测试了@juergen 给出的解决方案,但它给出了 PDOException,因为绑定变量的数量不匹配。无论没有参数,以下(不是那么优雅)代码都可以工作:

function searchPeople( $inputArr )
{
  $allowed = array(':first_name'=>'first_name', ':last_name'=>'last_name', ':age'=>'age', ':sex'=>'sex');

  $sql  = 'SELECT * FROM sf_guard_user WHERE 1 = 1';

  foreach($allowed AS $key => $val)
  {
      if( array_key_exists( $key, $inputArr ) ){
          $sql .= ' AND '. $val .' = '. $key;
      }
  }

  $query = $db->prepare( $sql );
  $query->execute( $inputArr );
  return $query->fetchAll();
}

用法:

$result = searchPeople(array(':first_name' => 'John', ':age' => '27'));
于 2012-06-27T18:21:00.880 回答