【问题标题】:PHP foreach loop to insert data into mysql with PDO only inserts first rowPHP foreach循环使用PDO将数据插入mysql仅插入第一行
【发布时间】:2014-01-19 13:51:35
【问题描述】:

我已经阅读了关于通过 foreach 和 PDO 插入内容的所有问题/教程,但仍然摸不着头脑。

我基本上是在尝试根据谁在我的商业联谊会中支付会费来批量插入/更新表格(因此是“兄弟”/“兄弟”)。

所有字段都是从 POST 中检索出来的,字段 1 是会费金额($amount),字段 2 是已付款的人数($num_paid) 字段 3 是一个用户 ID 数组,用于那些已付款 ($paid) 的用户,它是通过另一个文件中的 foreach 循环创建的复选框创建的。

我认为检查以确保输入正确的最佳方法是将 count($paid) 与 $num_paid 进行比较,并且只有在它们匹配时才继续。我愿意接受有关如何做得更好的建议,但它似乎按原样工作。

我正在尝试使用“foreach”从字段 3 ($paid) 循环遍历数组,以在表中插入新行作为每个已付款人的“信用”,但由于某种原因,它只插入第一个循环,然后以某种方式插入其余的空行。

表格设置有列:user_id(手动输入)、transaction_id(AI)、日期、贷方、借方、信息。

使用:"INSERT INTO finance VALUES(?,NULL,now(),?,?,?)"; 如果我插入 5 个用户,它将插入第一个带有 transaction_id x 的用户,然后再运行自动增量计数 4,但什么也不插入。所以下次我尝试插入时,transaction_id 比第一次多了5。

例如-- Try 1 插入一个 transaction_id 43 的行。 Try 2 插入一个 transaction_id 48 的行,但它们之间没有任何内容。

我尝试将数组传递给函数,然后以这种方式使用“foreach”循环遍历它,还尝试使用“foreach”循环调用函数并在每次插入时传递一个字符串。两者似乎工作相同。我很迷茫,因为如果自动递增列正在计数,它应该插入数据?

我认为这是所有相关代码...(添加了 PHP 标记以使其更具可读性。)

调用函数的表单数据处理

<?php
if (isset($_POST['amount']) && 
    isset($_POST['num_paid']) && isset($_POST['paid'])) {           

        $amount = saniString($_POST['amount']);
        $num_paid = saniString($_POST['num_paid']);
        $paid = $_POST['paid']; #this is an array of user id's for 
        #who has paid.  

        echo "<br /><br />";
        var_dump($paid);
        echo "<br /><br />";
        var_dump($num_paid);
        echo "<br /><br />";
        var_dump($amount);
        echo "<br /><br />";

        if (count($paid) != $num_paid) {
            echo "<p><b>You did not check the correct number of
                brothers. Please check your entries and try again.</b></p>";
        }
        elseif (count($paid) == $num_paid) {
            $match = true;
            echo "<p><b>Congrats. The numbers match.</b></p>";
        }

        if ($match === true) {
            if ($amount > 0) {
                $credit = $amount;
                $debit = 0;
            }
            elseif ($amount < 0) {
                $credit = 0;
                $debit = $amount;
            }
        else { 
            $credit = 0;
            $debit = 0;
        }           
        foreach ($paid as $dirtyId) {
            $result = updateFin($dirtyId,$broid,$credit,$debit,$dbh);
            var_dump($result);
        }                       
    }           
}
?>

准备/绑定/插入功能

<?php
function updateFin($dirtyId,$broid,$credit,$debit,$dbh) {
    $sql = "INSERT INTO finance VALUES(?,NULL,now(),?,?,?)";
    $query = $dbh->prepare($sql);

    #foreach ($paid as $dirtyId) { // please notice this is commented out

    $bro_paid = saniString($dirtyId);
    $info = "Dues from bro-ID: " . $bro_paid;

    $query->bindValue(1, $broid);
    $query->bindValue(2, $credit);
    $query->bindValue(3, $debit);
    $query->bindValue(4, $info);

    try {
        $result = $query->execute();                
    }
    catch (PDOException $e) {
        echo "<br />Insert of $credit, with info $info failed.";
        echo $e->getMessage();
        $result = false;
    }
    return $result;
    #}
}
?> 

var_dumping 我试图传递的值给了我我的期望 - $amount 是一个字符串 (50.00),$num_paid 也是一个字符串 (5),$paid 是一个充满 ID 的数组我正在尝试插入...

'saniString' 函数使用 strip_tags、htmlentities 和 stripslashes,如果相关的话......

如果我 var_dump($result) 它返回 bool(true),bool(false),bool(false),bool(false),bool(false)。鉴于我的结果,这是我所期望的,除了我不知道为什么查询失败并且我没有从 PDO 收到任何错误消息?

【问题讨论】:

  • 数组$paid在哪里?
  • $paid 来自 $_POST['paid'] var_dumps 作为数字索引数组。
  • finance 的表定义是什么? (特别是关于主键/唯一键)
  • 在调用updateFin()之前尝试$dbh-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);,如果有的话,这会给你错误。
  • 没有唯一键,但 trans_id 是主键并且会自动递增。 info 已编入索引,user_id - smallint,无符号 NOT NULL,无键。 trans_id - smallint,无符号 NOT NULL 主键 auto_increment,date - 日期时间,唯一。 credit - smallint NOT NULL, debit - smallint NOT NULL, info - varchar INDEXED 而且我认为这可能解决了我的问题...我怀疑 datetime 是唯一的,但使用 now() 设置可能会导致问题...但是现在我不确定如何删除它来测试它?

标签: php mysql arrays pdo foreach


【解决方案1】:

问题是由唯一的日期引起的。后续插入的日期与第二个相同,因此它们被忽略(同时自动增量增加)。 所以

alter table finance drop index date

[已编辑] 设置$dbh-&gt;setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 应该会导致重复插入以SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 引发异常(在我测试它时会发生)但是在创建 PDO 对象时默认情况下不会设置此属性。

如有疑问,即使没有异常,您也可以随时返回检查错误信息。 $err = $query-&gt;errorInfo();,对于重复条目,您将获得 $err[1] == 1062

【讨论】:

  • “你不能依赖例外”——你肯定有这样的说法的证据吗?
  • 也许你只需要告诉 PDO 抛出异常,而不是在每次查询执行后编写这么一屏代码?
  • 可能。但是 LouisK 说他在创建 PDO 对象时设置了它们。 (但没有提供那部分代码。)我会检查(下班后)。
  • 对象创建与异常有什么关系?当然,您必须创建一个对象才能使 PDO 工作。
  • @YourCommonSense 我已经仔细检查过,你是对的。我想知道 LouisK 是否只是假设在创建新 PDO 对象时设置了该属性,或者是否发生了其他事情。无论如何,谢谢。
【解决方案2】:

if (count($paid) != $num_paid) { 这一行中,您没有定义$match,如果此语句为真,则此行将引发未定义变量$matchif ($match === true) { 的错误

替换此代码块

if (count($paid) != $num_paid) {
    echo "<p><b>You did not check the correct number of
        brothers. Please check your entries and try again.</b></p>";
    $match = false;
}
elseif (count($paid) == $num_paid) {
    $match = true;
    echo "<p><b>Congrats. The numbers match.</b></p>";
}

【讨论】:

  • 好收获。不幸的是,这并没有解决它:(仍然只插入第一行,其余部分返回 bool(false)。
  • $broid$dbh 也未定义。你在哪里定义的?
  • $broid 在页面首次加载时定义,如果用户已登录。$dbh 是设置连接时创建的 PDO 对象。
猜你喜欢
  • 2013-04-05
  • 2015-05-10
  • 2012-06-19
  • 1970-01-01
  • 2015-08-20
  • 1970-01-01
  • 1970-01-01
  • 2019-01-21
  • 1970-01-01
相关资源
最近更新 更多