【问题标题】:PHP PDO - Passing and imploded array to a query placeholderPHP PDO - 将数组传递和内爆到查询占位符
【发布时间】:2013-08-23 15:15:09
【问题描述】:

首先,如果在其他地方回答了这个问题,我深表歉意,但我找不到任何东西。

以下代码有问题:

function register_user ($register_data) {
    global $db;
    array_walk ($register_data, 'array_sanitize');
    $register_data ['password'] = md5 ($register_data ['password']); 

    $fields = '`' . implode ('`, `', array_keys ($register_data)) . '`';
    $data   = '\'' . implode ('\', \'', $register_data) . '\'';

    $query = $db -> prepare ("INSERT INTO `users` (:fields) VALUES (:data)");
    $query -> bindParam (':fields', $fields);
    $query -> bindParam (':data', $data);
    $query -> execute ();
}

问题是执行正确,但是查询没有运行,行也没有插入到数据库中。

现在,如果我这样做:

$query = $db -> prepare ("INSERT INTO `users` ($fields) VALUES ($data)");
//$query -> bindParam (':fields', $fields);
//$query -> bindParam (':data', $data);
$query -> execute ();

一切都像魅力一样,所以我猜问题在于我如何将数据传递给占位符。

有人可以向我解释为什么这不起作用吗?我想首先正确理解它。

提前感谢您的帮助。

【问题讨论】:

    标签: php arrays pdo placeholder implode


    【解决方案1】:

    有两种不同的用例可以描述为将内爆数组传递给查询占位符。一种是在 SQL 中使用带有 IN() 子句的预处理语句。这个案例已经在this answer中全面介绍了。

    另一个用例是插入辅助函数,就像您的问题中提到的那样。我有一篇文章解释了如何创建 SQL 注入证明insert helper function for PDO_MYSQL

    鉴于这样的功能不仅向查询添加数据值,而且还向表和列名添加数据,因此准备好的语句不足以防止 SQL 注入。因此,这样的函数将需要自己的辅助函数,以保护命名的表和字段。这是 MySQL 的一个:

    function escape_mysql_identifier($field){
        return "`".str_replace("`", "``", $field)."`";
    }
    

    现在我们终于可以拥有一个函数,它接受一个表名和一个包含数据的数组,并对数据库运行一个准备好的 INSERT 查询:

    function prepared_insert($pdo, $table, $data) {
        $keys = array_keys($data);
        $keys = array_map('escape_mysql_identifier', $keys);
        $fields = implode(",", $keys);
        $table = escape_mysql_identifier($table);
        $placeholders = str_repeat('?,', count($keys) - 1) . '?';
        $sql = "INSERT INTO $table ($fields) VALUES ($placeholders)";
        $pdo->prepare($sql)->execute(array_values($data));
    }
    

    可以这样使用:

    prepared_insert($pdo, 'users', ['name' => $name, 'password' => $hashed_password]);
    

    完整的解释可以在上面链接的文章中找到,但简而言之,我们正在从输入数组键创建一个列名列表,并为 SQL VALUES() 子句创建一个逗号分隔的占位符列表。最后,我们将输入数组值发送到 PDO 的 execute()。安全、方便、简洁。

    【讨论】:

    • 代码不是从一开始就使用 PDO 编写的。我改编了它。我现在实际上正在学习 PHP,所以我必须适应。看到我必须继续使用 PDO,因为旧的方法将变得过时,我开始更改代码。至于 md5 加密,那只是暂时的。我计划更好地加密密码。谢谢你的帮助!我真的很感激。
    • 这解释了很多。无论如何,您是否找到了标记 wiki 页面底部的代码?您对此有任何疑问吗?
    • 是的,我想我明白了。我现在在脑海中运行想法。 :)
    猜你喜欢
    • 1970-01-01
    • 2020-08-28
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 2020-02-23
    相关资源
    最近更新 更多