0

对于 PDO 执行语句,我试图将任何静态信息(例如列名和数组字符串)转换为包含 MySQL 表中每一列的动态数组。

原始代码是:

$stmt = $conn->prepare("INSERT into data (`username,` `password`, `email`) VALUES username = :username , password = :password , email = :email ");

$stmt->execute(array(
    ':username' => $entry_username,
    ':password' => $entry_password,
    ':email' => $entry_email
));

到目前为止,我已经能够将 sql 语句更改为

$sql = "INSERT into DATA (`"  . implode('`,`', $columns) . "`) values (:" . implode(',:', $columns) . ")";
$stmt = $conn->prepare($sql);

但一直无法对执行数组做类似的事情,使其像语句一样动态变化。

我尝试在数组中添加一个 for 语句

for ($i = 0; $i < count($columns); $i++) {
    ':'.$columns[$i] => ${'entry_'.$columns[$i]};
}

但这没有奏效。

任何帮助将非常感激。提前致谢!

4

3 回答 3

0

基本上,您的代码将如下所示。

$entry = array(
    'username'  =>  $_POST['username'], //assuming it's comming from the post data or for instance $row['username'] if from previous select statement 
    'password'  =>  $_POST['password'],
    'email'     =>  $_POST['email']
    );
$sth = $dbh->prepare('INSERT into data (`username,` `password`, `email`) VALUES (:username, :password, :email)');
$sth->bindValue(':username', $entry['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $entry['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $entry['email'], PDO::PARAM_STR);
$sth->execute();

如果您希望动态创建绑定变量,则需要使用循环创建 bindValue 行:

$entry = array(
    'username'  =>  $_POST['username'], //assuming it's comming from the post data or for instance $row['username'] if from previous select statement 
    'password'  =>  $_POST['password'],
    'email'     =>  $_POST['email']
    );
$sth = $dbh->prepare('INSERT into data (`username,` `password`, `email`) VALUES (:username, :password, :email)');
foreach($entry as $key => $value) {
    $sth->bindValue(':'.$key, $entry[$key], PDO::PARAM_STR);
}
$sth->execute();

或在 foreach 内

$sth->bindValue(':'.$key, $value, PDO::PARAM_STR);

由于您的键是(用户名、密码、电子邮件),因此它们的键名将被初始化为 $key 变量,它们的值将被初始化为 $value 变量。在第一种情况下,它将产生:

$sth->bindValue(':username', $entry['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $entry['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $entry['email'], PDO::PARAM_STR);

这将被评估为:

$sth->bindValue(':username', $_POST['username'], PDO::PARAM_INT);
$sth->bindValue(':password', $_POST['password'], PDO::PARAM_STR);
$sth->bindValue(':email', $_POST['email'], PDO::PARAM_STR);

在第二种情况下,它将被直接评估。


请记住,在查询中动态创建列名是完全不可接受的。你必须有理由这样做。但是,也很难从其他开发人员那里读取不是完整的查询。动态创建绑定值就足够了。你可以让一个方法为你做这件事。例如,如果查询中的列名称与输入字段名称的别名方式相同,那么您将无事可做,只能执行查询。

假设你有那个辅助方法:

Class DBConnect {

    private $_driver     = "mysql";
    private $_dbname     = "xxxx";
    private $_host       = "xxxx";
    private $_user       = "xxxx";
    private $_password   = "xxxx";
    private $_port       = 3306;

    private $_dbh;

    public function __construct($driver = NULL, $dbname = NULL, $host = NULL, $user = NULL, $pass = NULL, $port = NULL) {
    $driver     = $driver   ?: $this->_driver;
    $dbname     = $dbname   ?: $this->_dbname;
    $host       = $host     ?: $this->_host;
    $user       = $user     ?: $this->_user;
    $pass       = $pass     ?: $this->_password;
    $port       = $port     ?: $this->_port;
    try {
        $this->_dbh  = new PDO("$driver:host=$host;port=$port;dbname=$dbname", $user, $pass);
        $this->_dbh->exec("set names utf8");
    } catch(PDOException $e) {
        echo    $e->getMessage();  
    }
}

    public function query($sql) {
        $sth = $this->_dbh->prepare($sql);

        foreach ($_REQUEST as $key => $value) {  
            if(is_int($value)) {
                 $param = PDO::PARAM_INT;
             } elseif(is_bool($value)) {
                 $param = PDO::PARAM_BOOL;
             } elseif(is_null($value)) {
                 $param = PDO::PARAM_NULL;
             } elseif(is_string($value)) {
                 $param = PDO::PARAM_STR;
             } else {
                 $param = FALSE;   
             }
             $sth->bindValue(":$key", $value, $param);
        }

        $sth->execute();
        $result = $sth->fetchAll();

        return $result;

    }
}

所以,让我们说在另一个类中你有很多查询,由方法分隔:

public function getFirstQuery() {
    $sql = "SELECT 
        col1, col2 
        FROM table1
        WHERE col3 = :col3;";
    $query = $this->_db->query($sql);
    return $query;
}

public function inserSecondquery() {
    $sql = "INSERT INTO 
        `table1` 
        (col1, col2) 
        VALUES
        ((SELECT 
        id 
        FROM table2 
        WHERE col8 = :col8), :post_field_5);";
    $query = $this->_db->query($sql);
    return $query;
}

假设您已将这些查询称为 query() 方法,该方法也获取数据,您可以选择一个您可以 foreach 检索数据的方法,以及您可以调用的插入方法来插入数据。这里唯一的规则是帖子字段应该以相同的方式命名,例如<input name="post_field_5" />


你也可以看看这里:PDO Dynamic Query Building


好的,看来您需要找到像 CodeIgniter 使用的活动记录库,或者......使用 CodeIgniter。

来自官方文档:

http://ellislab.com/codeigniter/user-guide/database/helpers.html

$this->db->insert_string();

此功能简化了编写数据库插入的过程。它返回格式正确的 SQL 插入字符串。示例: $data = array('name' => $name, 'email' => $email, 'url' => $url);

$str = $this->db->insert_string('table_name', $data);

第一个参数是表名,第二个参数是要插入的数据的关联数组。上面的例子产生: INSERT INTO table_name (name, email, url) VALUES ('Rick', 'rick@example.com', 'example.com')

所以,在你的情况下,你可以有这样的事情:

<form action="" method="post">
    <input type="text" name="username" value="testUser123" />
    <input type="password" name="password" value="yourPass666" />
    <input type="text" name="email" value="email@example.com" />
    <input type="submit" value="submit" />
</form>
<?php
//... extending CI
//... opening a method
$table = 'data';
//comming from somewhere, let's dynamically populated array but for testing purpose I will hardcode:
$columns('username', 'password', 'email');
foreach($columns as $column) {
    $data[$column] = $_POST[$column]; // this will produce $data=array('username'=>$_POST['username'],password=....);
}
$str = $this->db->insert_string($table, $data); 
?>

如果您在开始时提交表格,您将拥有:

INSERT INTO data (username, password, email) VALUES ('testUser123', 'yourPass666', 'email@example.com');

整个活动记录类文档(此处选择插入) http://ellislab.com/codeigniter/user-guide/database/active_record.html#insert

于 2013-08-19T12:16:16.183 回答
0

这是充分利用准备好的语句的完美情况。

试试这个:我有点假设变量将在 $columns 数组中被调用。

$stmt = $conn->prepare("INSERT into data 
      (username, password, email) VALUES( :username , :password, :email )");

$stmt->bindParam(':username', $username, PDO::PARAM_STR);
$stmt->bindParam(':password', $password, PDO::PARAM_STR);
$stmt->bindParam(':email', $email, PDO::PARAM_STR);

foreach ( $columns as $column ) {

    $username = $column['username'];
    $password = $column['password'];
    $email    = $column['email'];

    $result = $stmt->execute();

    if ( ! $result ) {
       // add some error checking code here
    }
}
于 2013-08-19T12:00:10.167 回答
-1

如果您不必坚持使用 for 循环,我会建议使用 foreach,这应该更容易(我也知道 for 的小问题)。

foreach ($element in $array) { code execution here }

然后将您的数组元素存储在 $element (或您喜欢的名称)中,您可以执行在那里找到的命令。

这是你要找的还是我弄错了?

于 2013-08-19T11:56:57.387 回答