【问题标题】:create PHP function for PDO insert query为 PDO 插入查询创建 PHP 函数
【发布时间】:2014-01-01 18:31:29
【问题描述】:

我尝试为 SQL/PDO 插入查询创建一个函数:

function InsertQuery ($table,$cols,$values) {
    global $pdo_conn;

    foreach($values as $values2) {
        $values2 = $values2;
    }
    $stmt='INSERT into $table (';
    foreach($cols as $cols2) {
        $stmt.=" ".$cols2.", ";
    }
    $stmt.=" ) VALUES ( ";
    foreach($cols as $cols2) {
        $stmt.=" :".$cols2." ";
    }
    $stmt.=" ) ";

    $stmt2 = $pdo_conn->prepare($stmt);
    foreach($cols as $cols2) {
    $stmt2->bindParam(':$cols2', $cols2);
    }
}

但我得到了错误:

可捕获的致命错误:第 30 行的 /home/integra/public_html/admin/includes/functions.php 中的 PDOStatement 类的对象无法转换为字符串

请耐心等待,因为我是 PDO 的新手并且刚刚习惯使用 MySQL

我把准备好的语句放错了还是我的 foreach 循环?

我认为该声明应如下所示:

$stmt2 = $pdo_conn->prepare('INSERT into $table (col1) values (:val1)');
$stmt2->bindParam(':$val1', $val);

这是我调用函数的方式:

$col=array('col1');
$val=array('val1');
InsertQuery ("table1",$col,$val);

更新:

好的,这是我的新代码:

global $pdo_conn;
foreach($values as $values2) {
    $values2 = $values2;
}
$stmt='INSERT into '.$table.' (';
foreach($cols as $cols2) {
    $stmt.=" ".implode(",", $cols2)." ";
}
$stmt.=" ) VALUES ( ";
foreach($cols as $cols2) {
    $stmt.=" :".implode(",", $cols2)." ";
}
$stmt.=" ) ";

$stmt2 = $pdo_conn->prepare($stmt);
foreach($cols as $cols2) {
    $stmt2->bindParam(':$cols2', $cols2);
}

但我现在得到关于内爆的错误:

警告:implode() [function.implode]:第 18 行 /home/integra/public_html/admin/includes/functions.php 中传递的参数无效

警告:implode() [function.implode]:第 22 行 /home/integra/public_html/admin/includes/functions.php 中传递的参数无效

我认为是因为只有一列和一个值,所以没有什么可以内爆的

【问题讨论】:

  • 阅读错误信息。该错误与 PDO 无关。它只是告诉您foreach() 的论点是错误的。 $values$cols 是什么?根据错误消息,它们似乎不是数组。
  • 实际上,我认为:$cols2 是在那里,但是 使用 双引号 字符串而不是单引号,这样$cols2插值并添加:
  • 你为什么还要做一个 foreach 循环来设置 $values2 等于它自己??
  • 谨慎引用。任何您希望在带引号的字符串中扩展变量的地方,都需要用双引号,而不是单引号。例如 $stmt2->bindParam(":$cols2", $cols2);
  • 该函数将用于许多插入查询,因此某些查询可能有 2 列要插入,而其他查询可能有更多

标签: php mysql sql pdo


【解决方案1】:

使用类型提示确保函数参数是数组:

function InsertQuery ($table, array $cols, array $values) {

确保您的 PDO 连接可访问。如果它是全球性的,你必须声明它(感谢@u_mulder):

    global $pdo_conn;

下面什么都不做,去掉它:

    foreach($values as $values2) {
        $values2 = $values2;
    }

使用内置数组函数而不是 foreach'ing 一切:

    $col_list = implode(",", $cols);
    $param_list = implode(",", array_fill(1,count($cols), "?"));

变量不会在单引号内展开。您需要使用双引号(感谢@MichaelBerkowski)。

另外,将 $stmt 用于 PDOStatement 对象,而不是用于 SQL 字符串。这令人困惑。

    $sql="INSERT into $table ($col_list) VALUES ($param_list)";

    $stmt = $pdo_conn->prepare($sql);

您不需要为 PDO 中的 bindParam() 编写 foreach 循环。您可以将一组值传递给execute()。而且您已经在数组中拥有了值,所以这真的很容易:

    $stmt->execute($values);

}

为了更加安全,请确保对列进行分隔,以防有人在列名中使用特殊字符或 SQL 关键字:

    $col_list = implode(",", array_map(function ($c) { return "`$c`" }, $cols));

并确保值在一个简单的数组中,而不是关联数组:

    $stmt->execute(array_values($values));

你的评论:

你能告诉我如何对 select 做同样的事情吗?我不确定它是如何工作的,就好像我有一个 where 子句我会在函数中用它做什么?

例如,可以设计一个带有参数$where 的函数,它是一个关联数组,其键是列名,其值是您要搜索的值。

假设生成的 WHERE 子句将这些列/值对包含为 AND 术语,并且所有比较都是相等的。

function SelectQuery($table, array $where) {
    global $pdo_conn;
    $sql = "SELECT * FROM `$table` ";
    $values = null;
    if ($where) {
        $sql .= "WHERE " . implode(" AND ", 
            array_map(function ($c) { return "`$c` = ?"; } array_keys($where)));
        $values = array_values($where);
    }
    $stmt = $pdo_con->prepare($sql);
    $stmt->execute($values);
}

当然,这仅支持您可以在 SELECT 中使用的可能表达式的一小部分,但我只是在这里演示一种技术。

如果您想要一个功能更全面的 PHP 查询构建器,请查看 Zend_Db_SqlDoctrine QueryBuilderLaravel query builder


如果我的服务器发生任何变化并且 PDO 停止工作,我可以在修复它时恢复到 MySQL。

PDO 自 2005 年以来一直很稳定,它不会停止工作,除非您更改 PHP 环境并禁用扩展或 mysql 驱动程序或其他东西。

而 ext/mysql 扩展停止工作。它目前已被弃用,PHP 已宣布他们将在未来的 PHP 版本中将其删除。

【讨论】:

  • 这似乎很完美! $values 是从哪里来的?
  • 也是$col_list,$c是哪来的?
  • $values 是 InsertQuery() 函数的参数之一。
  • 完美——谢谢。是否可以对 PDO 中的 SELECT 查询做类似的事情?
  • array_map() 自动循环遍历$cols 的元素并将每个元素作为参数传递给函数回调,我将其定义为anonymous function。我称那个论点为$c
【解决方案2】:

发生了一些事情:

首先,$cols$vals 应该是数组,但它们是字符串。

快速解决方法是将它们设为数组:

$col = array('col1');
$val = array('val1');
InsertQuery("table1", $col, $val);

其次,$pdo_conn 在函数范围内是未知的。将其设为参数或全局。

【讨论】:

  • $pdo_conn 也应定义为全局或作为参数传递。
  • 检查我的编辑,错误已经改变,我制作了 vars 数组
  • @charliejsford 你生成的 SQL 语句是错误的。做echo $stmt;自己看看。
【解决方案3】:

您也可以使用它从数组创建查询:

$myArray = array(
             'col1' => 'val1',
             'col2' => 'val2'
           );

$query = "INSERT INTO table (" . implode(", ", array_keys($myArray)) . ") VALUES (" . implode(", ", $myArray) . ")";

也许对你有用 http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

【讨论】:

  • 起初我认为这是一个好方法,但后来意识到这并不能清理输入。由于这是专门讨论 PDO,我认为修改以转义值会很好。
  • @BrianFLeighty 这是创建 sql 插入查询的简单方法。关于转义..您可以在例如之前转义值。在数组中。 'col1' => htmlspecialchars('val1') 或制作一个简单的函数来验证您的数据输入。这是给你的主意。您可以结合或另一种方式来解决您的问题。
猜你喜欢
  • 2013-09-03
  • 1970-01-01
  • 1970-01-01
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-26
  • 2018-11-28
相关资源
最近更新 更多