Php 添加和更新具有多个条目的Mysql子表

Php 添加和更新具有多个条目的Mysql子表,php,mysql,arrays,parent-child,Php,Mysql,Arrays,Parent Child,我在mysql中有两个表:一个名为“grants”的主表和一个名为“goals”的子表。Grants有一个id字段以及一组其他字段,而goals有一个目标名称和一个grant_id将其链接到Grants表 在html表单上,用户可以添加或编辑任意多个目标(我正在使用Javascript添加新的输入)。表单还可以添加任何以前的目标,并将其添加到表单中 <div id="goals"> <?php $goals = getGoalsById($_GE

我在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')" />
这对于更新现有目标非常有效,因为传递的键是目标表中的id。但是,我遇到的问题是,当他们有新的目标时,从表单传递的$goals数组总是从0开始,因此插入查询尝试使用0、1、2等作为插入id。我希望它自动选择目标表中的下一个可用id


我曾尝试自动填充我认为可能是新目标id的内容,但这是一个坏主意,因为多人可能一次访问该站点,并且可能会重叠。感谢您的帮助

我将对这个过程进行一些假设,以使其适用于您。

  • 新条目的表格为空
  • 在更新的情况下,表单从数据库填充为 它站着
  • 更新时,表单将从数据库中重新显示,并在 上面说更新已经发生了
  • 这不是银行数据或超临界故障容忍数据。哪个 对于你的申请,我认为不是。这是一种 处理行政数据
我建议的后期处理如下。 我建议将插入过程稍微分开一点

  • 在主表中插入/更新。如果是insert,则从装箱行中获取记录Id,用作目标表的外部键

  • 删除目标表中与外部键相关的所有条目。这将运行,即使还没有进入,并将清除所有目标,如果有任何。从字面上撕下所有行并重新插入

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

  • 使用从数据库中提取的数据再次显示表单。如果出现错误并将结果输出回表单,则在从目标表中清除数据后,如果更新过程中出现错误,则用户始终可以再次更新。如果数据丢失,用户将看到问题并重试 同样,不是我如何处理银行数据,而是对于具有无限多目标的表单,这是我找到的最简单的解决方案。

    祝你好运

    因此,在G+中进行讨论后,我最终把事情分了开来:

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

    
    
    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();
        }
    
    <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>
    
    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();
    
    }