【问题标题】:mysql_query to PDO and prepared statementsmysql_query 到 PDO 和准备好的语句
【发布时间】:2011-08-19 22:28:19
【问题描述】:

我的 CMS 中有这个功能,它将字段和值的变量列表插入到两个不同的表中;一种是静态索引表,一种是动态索引表。这是函数:

function insertFields($fields)
{
   $stdfields = array();
   $extfields = array();

   /* Separate the fields based on if the fields is standard or extra.  $this->fields is a csv list of the defined extra fields */
   foreach($fields as $field => $value)
   {
      $fields[mysql_real_escape_string($field)] = mysql_real_escape_string($value);

      if(strstr($this->fields, $field))
         $extfields[$field] = $value;
      else
         $stdfields[$field] = $value;   
   }

   //Build the 2 queries -- Maybe there is a better way to do this?
   $extfieldcount = count($extfields);
   $stdfieldcount = count($stdfields);
   $stditers = 0;
   $extiters = 0;

   foreach($extfields as $field => $value)
   {
      if($extiters != $extfieldcount)
      {
         $extfields.= $field.", ";
         $extvalues.= "'".$value."', ";
      }
      else
      {
         $extfields.= $field." ";
         $extvalues.= "'".$value."' ";
      }
      $extiters++;
   }

   foreach($stdfields as $field => $value)
   {
      if($stditers != $stdfieldcount)
      {
         $newfields.= $field.", ";
         $newvalues.= "'".$value."', ";
      }
      else
      {
         $newfields.= $field." ";
         $newvalues.= "'".$value."' ";
      }
   $stditers++;
   }

   //Inset the standard fields
   $stdquery = "INSERT INTO masteridx (".$newfields.") VALUES (".$newvalues.")";
   $this->dbQuery($stdquery);

   /* not perfect. I need a better way to find the id that was inserted, so I can combine three queries into at least two */

   $findlastquery = "SELECT `id` FROM `masteridx` WHERE `slug`='".$fields['slug']."' LIMIT 1";
   $result = $this->dbQuery($findlastquery);
   $result = mysql_fetch_assoc($result);
   $tempfield = "id, ";
   $tempvalue = "'".$result['id']."', ";

   //Insert the extra fields
   $extquery = "INSERT INTO ".$this->type." (".$tempfield.$extfields.") VALUES (".$tempvalue.$extvalues.")";
   $this->dbQuery($extquery);

}

所以对于准备好的语句,我不能绑定字段,只能绑定值,对吗?因此,如果我执行以下操作,我仍然必须逃离这些领域:

for ($i = 0; $i <= $stdfieldcount; $i++)
{
    if($i < $stdfieldcount)
    $qs.= '?, ';
    else
    $qs.= '? '; 
}

$sth = $dbh->prepare("INSERT INTO masteridx ({$stdfields}) VALUES ({$qs})");
$sth->execute($array_of_stdfield_values);

如果我仍然必须逃离这些领域,这里有什么意义?此函数最终将采用包含多篇文章及其字段的数组。字段本身每次也会有所不同。我认为当我第一次查看准备好的语句时,我可以只给它一个字段数组和一个值数组,但我想情况并非如此。

我的问题是,你们将如何实现这一点?我想开始与数据库无关,而 PDO 看起来是一个很好的方法。

【问题讨论】:

    标签: php mysql pdo prepared-statement


    【解决方案1】:

    PHP 提供了很多方便的函数,它们可以完成很多您需要手动完成的工作。

    • PDO 在您的 SQL 语句中支持 命名参数,因此您可以传递一个键/值数组,其中键与您的命名参数占位符匹配。
    • join() 函数对于构建逗号分隔列表非常有用。
    • 存在许多用于操作arrays 的函数。
    • 某些函数允许您提供callback(在 PHP 5.3 中可以是一个闭包),以动态处理数组。

    示例(未测试):

    function insertFields($fields) {
        $columns = join(",", array_map(
            function($col) { return "`".preg_replace("/`/gu","``",$col)."`"}, 
            array_keys($fields)));
    
        $params = join(",", array_map(
            function($col) { return ":".preg_replace("/[`\s]/gu","",$col)},
            array_keys($fields)));
    
        $stdquery = "INSERT INTO masteridx ({$columns}) VALUES ({$params})";
        $stmt = $pdo->prepare($stdQuery);
        $stmt->execute($fields);
    }
    

    【讨论】:

    • 哇,这一切都非常有帮助 - 我在很多地方都在用 foreach 循环构建 mysql 查询......这看起来容易了 200 万倍。我不知道你可以传递命名参数,所以我将不得不玩这个。非常感谢您花时间教我一些非常有用的东西!
    • 使用 PHP 的内置函数,如 join、array_keys、array_map 等,不仅更容易编码,而且性能比你用 PHP 编写的等效代码好很多。任何人都值得花时间阅读 PHP 手册页并练习使用内置函数。
    • 毫无疑问,我在手册页上花了很多时间——但对我来说,如何将函数像这样链接在一起以在 1 行代码中完成某些事情并不总是显而易见的,这通常需要我 10- 15.有时我认为手册页可以使用更实际的示例。在这个网站上浏览,提出问题比手册教给我的东西更多。
    • 是的。参考文档和面向任务的文档之间存在真正的区别。
    猜你喜欢
    • 2012-08-23
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2010-11-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多