【问题标题】:PHP + MySQL Issue - where did I go so wrong?PHP + MySQL 问题 - 我哪里错了?
【发布时间】:2016-06-16 13:21:57
【问题描述】:

这里是挖掘。我一遍又一遍地查看我的代码,直到我的头脑麻木,仍然无法弄清楚问题出在哪里。

我正在使用可在类似 CRM 的应用程序的后端使用的删除功能。表单内有一个用户列表,每个注册用户都有一个复选框,还有一个提交按钮,用于运行代码以通过他们的 ID 从数据库中删除选定的用户。

复选框在 foreach 循环中生成,该循环使用从选择查询返回的数组填充表。每个用户的每个复选框行都是这样的:

<input type="checkbox" name="checked[]" value="<?php echo ($userfromforeach['id']); ?>">

表单的提交按钮包含(name="deleteusers")

而表单提交的实际删除代码如下:

// Delete users by selected as posted by form
if(isset($_POST['deleteusers']))
{
    foreach($_POST['checked'] as $user)
    {
        $query = "
            DELETE
            FROM $usertable
            WHERE id = $user
        ";

        try
        {
            // These two statements run the query against your database table.
            $stmt = $db->prepare($query);
            $stmt->execute();
        }
        catch(PDOException $ex)
        {
            die("MySQL execution error, please contact technical support.");
        }

    }
    // $_POST['checked'] = NULL;
    header("Refresh:0");
}

由于某种我不知道的原因,一切似乎都在正确触发,但是没有从数据库中删除任何记录。没有返回 MySQL 错误,当我将 print_r 取出 $_POST['checked'] 变量时,它会按预期显示:

Array ( [0] =&gt; 122 [1] =&gt; 115 )

^ 每个键的值是用户的 ID。

有什么想法吗?我是否只是因为错过了一些完全基本的东西而在自己的脑海中提出了一个问题?非常感谢您的帮助。

【问题讨论】:

  • 回显您正在生成的 SQL - 它看起来是否正常。另外-您没有正确使用准备好的语句。这个想法是你用占位符准备语句一次,然后执行多次,每次传入不同的参数。
  • 你的foreach 好像不见了{
  • 你使用的不是准备好的语句
  • 回显 SQL 确实看起来应该也...我知道,我没有正确使用准备好的语句 - 我对 PHP 比较陌生,这是一个演示,我有一个时间限制,准备好的语句让我感到困惑,所以对于非生产演示,我决定运行未准备好的查询就可以了。 - 感谢您的提醒。抱歉,错字 - 在上面的问题中编辑。
  • echo $query = "DELETE FROM $usertable WHERE id = $user"; 并粘贴它返回的内容

标签: php mysql forms


【解决方案1】:

当您使用 for/foreach 函数循环某些内容时。您必须用花括号将整个重复逻辑包裹起来。否则只会执行一个声明 在您的情况下,将字符串分配给 $query 变量。就是这样。虽然还有很多地方需要改进。但要解决这个特定问题,您的 foreach 应如下所示:

foreach($_POST['checked'] as $user)
{
    $query = "DELETE FROM $usertable WHERE id = $user";
    try
    {
        $stmt = $db->prepare($query);
        $stmt->execute();
    }
    catch(PDOException $ex)
    {
        die("MySQL error, blah blah blah...");
    }
}

【讨论】:

  • 我也错过了。好收获!
  • 对不起,我的朋友 - 我一直在运行 debian 的 VM 中编写此代码,目前 Guest-Host 剪贴板无法正常工作,因此我无法复制粘贴我的代码超过。花括号确实覆盖了整个循环语句 - 我已经适当地编辑了这个问题。
【解决方案2】:

为什么在循环中运行删除查询,如果用户选择 200 条记录怎么办?您将触发查询 200 次?

我建议您编写您的 PHP 登录以满足以下查询

DELETE from tablename WHERE id IN (1,2,3,...,200);

如果您有连续的 ID,请使用 BETWEEN:

DELETE from tablename WHERE id BETWEEN 1 AND 200;

仅对某些 ID 进行限制:

DELETE from tablename WHERE id BETWEEN 1 AND 200 AND id<>47;

这样查询只会被触发一次,前提是 MySQL 查询的输入 (ID) 是通过 PHP 循环预先生成的。

【讨论】:

  • 你说得对,我的代码效率低下。不是很糟糕,因为一次触发的最大查询数只有 25 个,但仍然应该更好地简化。
【解决方案3】:
if(isset($_POST['deleteusers'])) <-- submit button with the name "deleteusers"
    {   

        foreach($_POST['checked'] as $user)
        {
            $query = "DELETE FROM $usertable WHERE id = :user";     
            try
            {
                $stmt = $db->prepare($query);
                $stmt->bindParam(':user', $user);
                $stmt->execute();
            }
            catch(PDOException $ex)
            {
                die("MySQL error, blah blah blah...");
            }
        }
    }

您可以使用此查询在一条语句中运行此语句

$query = "DELETE FROM $usertable WHERE id IN (:user)";      

$stmt->bindParam(':user',implode(",",$_POST['deleteusers']));

【讨论】:

  • 那不是$query = "DELETE FROM $usertable WHERE id IN (".implode(",",$_POST['checked']).")"; 吗? deleteusers 变量是通过单击提交按钮设置的,而 checked 变量包含要删除的用户 ID 的数组...
  • 在 implode 结果查询为 $query = "DELETE FROM $usertable WHERE id IN (122,115)";这是正常的删除查询
【解决方案4】:

好吧,我是个白痴。

经过大量挖掘,事实证明这个问题是我在引导程序的模态弹出框中的提交按钮,显然即使根据我的理解,模态实际上只是在页面中隐藏和显示一个 div,任何来自模态 div 的帖子数据不会被传回主页。 >:[因此,我能想到的唯一解决方案是在单击删除按钮时从 javascript 中设置 $_POST['deleteusers'] 变量...保姆真是太痛苦了...

无论如何,谢谢大家的帮助,我将标记大字节数的答案,因为他涵盖了另外两个非常重要的考虑因素 - 正确使用准备好的语句以及如何将流程简化为一个查询,节省资源和理论上的 CPU时间。

【讨论】: