PDO插入查询,为什么这不起作用

时间:2012-05-08 14:24:17

标签: php pdo

我用mysqli愚蠢地构建了我的web应用程序。现在,我正在尝试将我的数据抽象层转换为pdo,但由于某种原因,插入查询给我带来了麻烦。我的快捷插入函数是从控制器调用的,我希望将它保存在名称格式中,并以表名和列/值数组作为参数。

我评论了我认为问题出在哪里。请帮忙。

function insert($table, array $columns_values) {        

    // connect to db
    $dbh = $this->db_connect();

    $i = 0;

    $columns = array();
    $values  = array();
    $params  = array();

    foreach($columns_values as $column => $value) {

        $i++;

        $param = array($i => $value);
        array_push($params, $param);

        array_push($columns, $column);
        array_push($values, '?');

    }

    // turn arrays into comma separated list
    $columns =      implode(",", $columns);
    $values  =      implode(",", $values);


    $stmt = $dbh->prepare("INSERT INTO $table ($columns) VALUES ($values)");


    foreach ($params as $param_stmt) {

             // i think this is where the problem is
            foreach ($param_stmt as $placeholder => $value) {

                $stmt->bindParam($placeholder, $value);

            }


    }

    $stmt->execute();

    return $stmt;

} // end insert()

3 个答案:

答案 0 :(得分:2)

我不会这样做。几分钟后,我想出了这个:

/**
 * Function to insert a list of values to the database.
 * 
 * @param PDO    $pdo
 * @param string $table
 * @param array  $columns_values
 *
 * @throws \Exception
 * @throws \PDOException
 */
function insert_to_db(PDO $pdo, $table, array $columns_values) {
    //Some data validation.
    if (empty($columns_values)) {
        throw new \Exception("Insert at least one value.");
    }
    if (empty($table)) {
        throw new \Exception("Table may not be empty.");
    }

    //Implode all of column names. Will become the columns part of the query.
    $str_columns = implode(", ", array_keys($columns_values));

    //Implode all column names after adding a : at the beginning.
    //They will become the placeholders on the values part.
    $prepared_column_names = array_map(function ($el) {
        return ":$el";
    }, array_keys($columns_values));
    $prepared_str_columns  = implode(", ", $prepared_column_names);

    //The query itself. Will look like "INSERT INTO `$table` (col1, col2, col3) VALUES (:col1, :col2, :col3);"
    $query = "INSERT INTO `$table` ($str_columns) VALUES ($prepared_str_columns);";

    //Prepare the query
    $stmt = $pdo->prepare($query);

    //Iterate over the columns and values, and bind the value to the placeholder
    foreach ($columns_values as $column => $value) {
        $stmt->bindValue(":$column", $value);
    }

    //Execute the query
    $stmt->execute();

}

我改变的事情

  1. 我没有在函数内部实例化PDO对象。函数需要才能工作,所以它应该是参数之一!
  2. 如果出现错误,我会抛出异常。这是处理错误的更好方法。
  3. 我使用命名占位符而不是未命名的占位符(:name vs ?)。如果您需要调试,可以生成更易读,更易于查询的查询。
  4. 为代码添加了评论。再一次,你了解你现在写的是什么,但是从现在起6个月后你会这么做吗?
  5. 我利用array_keys()自动生成一个充满键的数组(即列),而不是循环并手动添加一个。
  6. 一些提示

    • 实例化PDO对象时,请确保在出错时抛出PDOException个!像这样:

      new PDO($dsn, $user, $pass, array(PDO::PARAM_ERRMODE => PDO::ERRMODE_EXCEPTION));
      

      $pdo = new PDO($dsn, $user, $pass);
      $pdo->setAttribute(PDO::PARAM_ERRMODE, PDO::ERRMODE_EXCEPTION);
      

      这样,你不需要每次都明确地检查错误,你使用一个try catch块来表示整个事情,并且你很好:

      try {
          insert_to_db($pdo, $table, $array_of_columns_and_values);
      }
      catch (\Exception $e) { //Will catch all kinds of exceptions, including PDOExceptions
          echo $e->getMessage();
      }
      

答案 1 :(得分:1)

您尚未检查您的prepare()实际上是否成功:

$sql = "INSERT ....";
$stmt = $dbh->prepare($sql);
if (!$stmt) {
    die($sql . $dbh->errorInfo());
}

永远不要假设查询成功,特别是当您完全动态地构建一个查询时。

答案 2 :(得分:1)

无需查看原始$columns_values数组的内容。

希望有所帮助

<?php 
function insert($table, $values){
    $dbh = $this->db_connect();

    $fieldnames = array_keys($values[0]);

    $sql = "INSERT INTO $table";
    /*** set the field names ***/
    $fields = '( ' . implode(' ,', $fieldnames) . ' )';
    /*** set the placeholders ***/
    $bound = '(:' . implode(', :', $fieldnames) . ' )';
    /*** put the query together ***/
    $sql .= $fields.' VALUES '.$bound;

    //INSERT INTO testtable( id ,col1 ,col2 ) VALUES (:id, :col1, :col2 )

    /*** prepare and execute ***/
    $query = $dbh->prepare($sql);
    foreach($values as $vals){
        $query->execute($vals);
        /*  Array
        (
        [id]   =
        [col1] = someval1
        [col2] = Someval21
        )*/
    }

}
//Multi Insert
$insert = array(array('id'=>'','col1'=>'someval1','col2'=>'Someval21'),
                array('id'=>'','col1'=>'someval2','col2'=>'Someval22'),
                array('id'=>'','col1'=>'someval3','col2'=>'Someval23'),
                array('id'=>'','col1'=>'someval4','col2'=>'Someval24')
);

insert('testtable',$insert);
?>