使用PHP PDO进行动态查询

时间:2010-12-27 13:22:04

标签: php pdo

我正在试图弄清楚如何将我的历史脚本从mysql_query()转换为PDO。我有一个包含4个输入字段的表单,您可以随机选择。这意味着可以选择0,1,2,3,4个字段,具体取决于您要获取的信息。

我试过像这样查询db:

$q = $db->prepare('SELECT date,
                          name,
                          action
                   FROM history
                   WHERE name = :name
                   AND action = :action');

$q->bindParam(':name', $Name, PDO::PARAM_STR, 20);
$q->bindParam(':action', $Action, $PDO::PARAM_STR, 20);
$q->execute();

但如果我没有选择任何字段并希望显示整个历史记录,则此功能无效。

使用mysql_query()我会这样做:

mysql_query('SELECT date,
                    name,
                    action
             FROM history
             $Name
             $Action');

这意味着如果没有$ Name或$ Action,它们就不会包含在查询中。

我应该将旧查询复制/粘贴到$ q = $ db-query('')吗?但这种做法违背了使用PDO的目的。

1 个答案:

答案 0 :(得分:10)

您始终可以为符合列名的参数指定默认值。

这样,您的查询将在默认情况下以where column = column结尾,当存在值时,它将为where column = value

编辑:

当然,我的逻辑略有缺陷,因为bindParam不起作用。相反,您应该根据设置的参数逐步构建语句。

/* Start with the most general case for the sql query.
 * The where part always evaluates to true and will thus
 * always return all rows and exists only to make appending
 * further conditions easier.
 */

$q = 'SELECT date, name, action FROM history WHERE 1';

/* Prepare a params array in any way you wish. A loop might be more
 * efficient if it is possible, but since in this example you have
 * only 2 variables, it didn't seem necessary 
 */

$params = array();
if (! empty($Name)) {
    $params['name'] = $Name;
}

if (! empty($Action)) {
    $params['action'] = $Action;
}

/* When the params array is populated, complete the sql statement by
 * appending the param names joined with ANDs 
 */

foreach ($params as $key => $value) {
    $q .= sprintf(' AND `%s` = :%s', $key, $key);
}

/* When the query is complete, we can prepare it */
$stmt = $db->prepare($q);

/* Then bind the values to the prepared statement 
 */

foreach ($params as $key => $value) {
    // Using bindValue because bindParam binds a reference, which is
    // only evaluated at the point of execute
    $stmt->bindValue(':'.$key, $value);
}

/* Now we're ready to execute */
$stmt->execute();

在这个例子中,empty检查可以在我们完成sql语句的循环中完成,但是这会给你一个不那么一般的例子。

此示例还省略了bindValue的类型参数,但这很容易实现,例如通过将数组值更改为具有类型作为成员的对象或数组,或通过在分配循环内键入duck。

只要您提供初始(一般情况)查询以及params数组,查询构建就可以以这种形式轻松放入一个适用于所有数据库查询需求的函数中。