0

我在 mysql 中有两个表:一个名为“grants”的主表和一个名为“goals”的子表。Grants 有一个 id 字段以及一堆其他字段,goals 有一个目标名称和一个 grant_id 以将其链接到 grants 表。

在 html 表单上,用户可以根据需要添加或编辑任意数量的目标(我正在使用 Javascript 来添加新输入)。表单还会添加任何先前的目标并将它们添加到表单中。

<div id="goals">
        <?php
        $goals = getGoalsById($_GET['id']);
        if (empty($goals)) echo "<p>Goal 1: <input type='text' size='40' name='goals[]' /></p>";
        else {
            $i = 1;
            foreach($goals as $goal) {
                echo "<p>Goal {$i}: <input type='text' size='40' name=\"goals[{$goal['id']}]\" value=\"{$goal['goal']}\" /></p>";
            $i++;
            }

        }
        ?>
    </div>
<input type="button" value="Add goal" onClick="addInput('goals')" />

当我提交表单时,我有以下语句来插入或更新目标:

foreach($goals as $key=>$goal) {

        $sql_goals_add[] = "INSERT INTO goals (id, goal, grant_id) VALUES ($key,:goalnew,$grant_id) ON DUPLICATE KEY UPDATE goal = :goalupdate";
        foreach ($sql_goals_add AS $sql_goal) {
            $stmt_goal = $DBH->prepare($sql_goal);
            $stmt_goal->bindValue(':goalnew', $goal, PDO::PARAM_STR);
            $stmt_goal->bindValue(':goalupdate', $goal, PDO::PARAM_STR);
        }
    $stmt_goal->execute();
    }

这适用于更新现有目标,因为传递的键是目标表中的 id。但是,我遇到的问题是当他们有新目标时,从表单传递的 $goals 数组总是从 0 开始,因此插入查询尝试使用 0、1、2 等作为插入 ID。我宁愿让它自动选择目标表中的下一个可用 id。

我试图自动填充我认为可能是新目标 ID 的内容,但这是一个坏主意,因为多个人可能会同时访问该站点并且它可能会重叠。任何帮助表示赞赏!

4

2 回答 2

1

我将为这个过程为你工作做一些假设。

  • 在新条目的情况下,表格是空白的。
  • 在更新的情况下,表单是从数据库中按原样填充的。
  • 更新时,表格会从数据库中重新显示,顶部有一条说明已发生更新的注释。
  • 这不是银行数据或超临界容错数据。对于您的应用程序,我认为不是。它是一种处理行政数据的表格。

我建议的 Post 过程如下。 我建议将您的插入过程分开一点。

  1. 插入/更新到主表中。如果是插入,则从 crated 行中获取记录 ID 以用作目标表的外部键。

  2. 从您的目标表中删除与外部键相关的所有条目。即使还没有条目,这也会运行,并且如果有任何目标,它将清除所有目标。从字面上撕掉所有行并进行新的插入。

  3. 使用主表的记录 id 作为插入的外部键,遍历 post 数组的目标部分。跟踪原始目标记录 ID 以进行更新是非常困难的。因为您清除了表格,所以您不必担心它,因为该数据也在帖子中。如果此人编辑了目标的措辞,则您无需检测到目标是否需要更新,因为它们都会立即重新输入。

  4. 使用从数据库中提取的数据再次显示表单。如果出现错误并且您将结果输出回表单中,如果在从目标表中清除数据后更新过程中出现故障,用户可以随时再次更新。如果数据丢失,用户将看到问题并重试。

同样不是我如何处理银行数据,而是对于具有无限数量目标的表格,这是我找到的最简单的解决方案。
祝你好运

于 2013-07-12T17:04:06.303 回答
0

所以,在 G+ 讨论完之后,我最终把事情分开了:

1) 重命名传递给goalsNew 和goalsExisting 的数组 2) 更改函数以分别解析每个数组,以便对新条目执行插入,但对现有条目执行更新。以下是完整的代码,以防万一。:)

<div id="goals">
        <?php
        $goals = getGoalsById($_GET['id']);

        if (empty($goals)) echo "<p>Goal 1: <input type='text' size='40' name='goalsNew[]' /></p>";
        else {
            $i = 1;
            foreach($goals as $goal) {
                echo "<p>Goal {$i}: <input type='text' size='40' name=\"goalsExisting[{$goal['id']}]\" value=\"{$goal['goal']}\" /></p>";
            $i++;
            }
        }
        ?>
    </div>

这是完成这一切的函数(我将它从 DealingWithGoals 重命名为 dealWithChildren,因为这将用于多个子表,而且还因为新父亲应该有一个名为 dealWithChildren 的函数!

function dealWithChildren($childType, $childNew, $childExisting, $grant_id) {

$fieldName = substr($childType, 0, -1);

dbConnect();
global $DBH;

try {

// If there are no children at all, delete them all

if(empty($childNew) && empty($childExisting)) {
        $sql_child_delete = "DELETE FROM $childType WHERE grant_id = $grant_id";
        $stmt_child = $DBH->prepare($sql_child_delete);
        $stmt_child->execute();
    }

// If the user removed a child, delete those children
    if(!empty($childExisting)) {
        $sql_child_delete = "DELETE FROM $childType WHERE grant_id = $grant_id AND id NOT IN (";
        $i = 0;
        $len = sizeof($childExisting);
        foreach($childExisting as $key=>$child) {
            $sql_child_delete .= $key;
            if ($len > 1 && $i < $len-1) $sql_child_delete .= ",";
            $i++;
        }
        $sql_child_delete .= ")";
        $stmt_del_child = $DBH->prepare($sql_child_delete);
        $stmt_del_child->execute();
    }
// If a user added any children
    if(!empty($childNew)) {
        foreach($childNew as $key=>$child) {
            $sql_child_add[] = "INSERT INTO $childType ($fieldName, grant_id) VALUES (:childnew,$grant_id)";
            foreach ($sql_child_add AS $sql_child) {
                $stmt_child = $DBH->prepare($sql_child);
                $stmt_child->bindValue(':childnew', $child, PDO::PARAM_STR);
            }
        $stmt_child->execute();
        }
    }

// If a user updated any children
    if(!empty($childExisting)) {
        foreach($childExisting as $key=>$child) {
            $sql_child_update[] = "UPDATE $childType SET $fieldName = :childupdate WHERE id = $key";
            foreach ($sql_child_update AS $sql_child) {
                $stmt_child = $DBH->prepare($sql_child);
                $stmt_child->bindValue(':childupdate', $child, PDO::PARAM_STR);
            }
        $stmt_child->execute();
        }
    }


} catch (PDOException $f) {
    echo 'Database query failure: ' . $f->getMessage();
    //exit;
}

dbDisconnect();

}
于 2013-07-14T01:23:11.593 回答