忽略特定的WHERE标准

时间:2012-06-27 17:10:22

标签: php mysql pdo where-clause

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

这是一个虚构的例子来说明我的目标

$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 个答案:

答案 0 :(得分: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 for PDO {/ 1}}

答案 1 :(得分: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');

答案 2 :(得分: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

答案 3 :(得分: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'));