首页 > 解决方案 > 如何插入具有多个值的多行,但仅适用于旁边勾选复选框的项目

问题描述

我正在为音乐数据库编写唱片工具。

艺术家可以将曲目、单曲、EP 和专辑全部插入数据库的单独表中。

将曲目放在自己的单独表中允许将相同的曲目附加到多个单曲、EP 和专辑,同时只需要在数据库中为该曲目提供一条记录。

这意味着各个曲目页面可以有一个自动生成的链接列表,这些链接返回到它们出现的单曲、EP 和专辑。使通过网站导航数据库的体验更加顺畅。

我已经到了编写一个工具的地步,该工具可以将数据库中给定艺术家的任何现有曲目附加到专辑页面上。

我正在使用数据库中另一个名为“trackconnections”的表来创建来自曲目表的曲目 ID 和来自专辑表的专辑 ID 之间的关系链接,还有一个名为Albumtracknum的附加列可用于输出曲目中的曲目在相册页面上查询时正确的顺序。

该工具的代码位于标有“将现有曲目附加到专辑”的按钮后面。该工具的代码如下:

    if (isset($_POST['attachexistingtracktoalbum-submit'])) {
    
require "includes/db_connect.pdo.php";

$artistid = $_POST["artistid"];
$albumid = $_POST["albumid"];

echo '<strong>Select each track you would like to add to this album below and type in the track number you want it to have on the album in the box underneith the name of each selected track.</strong><br><br>';

$stmt = $pdo->query("SELECT * FROM track WHERE artist_id = '$artistid'
order by trackname");
while ($row = $stmt->fetch())
{           
    echo '<form action="includes/attachexistingtracktoalbum.inc.php" method = "post">';
    echo '<div class="checkbox">';
    echo '<label>';
    echo "<input type='checkbox' name='trackid[]' value='".$row['id']."' />";
        echo '<span class="cr"><i class="cr-icon glyphicon glyphicon-ok"></i></span>';
    echo ' '.$row['trackname'];
    echo '</label>';
    echo "<br><label for='albumtracknum'>Track number:</label><br>
    <input type='text' name='albumtracknum[]'>
    <input type='hidden' name='albumid[]' value='".$albumid,"'>
    <br><br>";
    echo '</div>';

}
?>
  <input type="hidden" name="albumidforreturn" value="<?php echo $albumid;?>">
  <button type="submit" name="attachexistingtracktoalbum-submit">Attach track(s) to album</button>
  
<?php }
else {
header("Location: /index.php");
 exit();
}?>

(注意:此处的帖子数据未针对 sql 查询进行清理,因为它已从原始专辑页面以隐藏形式传递)

这会生成一个页面,其中包含当前艺术家的所有曲目名称,列表中带有复选框,每个曲目名称后面都有一个数据输入框,用于输入要添加到的专辑的曲目编号。

提交表单然后移交给以下包含代码:

    if (isset($_POST['attachexistingtracktoalbum-submit'])) {

require "db_connect.pdo.php";
 
 $albumid = implode(',',$_POST['albumid']);
 $trackid  = implode(',',$_POST['trackid']);
 $albumtracknum  = implode(',',$_POST['albumtracknum']);
 $albumidforreturn = $_POST['albumidforreturn'];

// echo 'albumid: '.$albumid.'<br>';
// echo 'trackid: '.$trackid.'<br>';
// echo 'albumtracknum: '.$albumtracknum.'<br>';
 
  $sql = "INSERT INTO trackconnections (albumid, trackid, albumtracknum) VALUES (?,?,?);";
  $stmt= $pdo->prepare($sql);
  $stmt->execute([$albumid,$trackid,$albumtracknum]);
    header("Location: ../albumdetail.php?albumid=$albumidforreturn");
    exit();
}
else {
header("Location: ../index.php");
 exit();
}

(注意:注释掉的回声用于测试前一个表单的输出)

我遇到的两个问题是我的“将现有曲目附加到专辑”表单提交:

1. 传递太多数据。

生成的表单应仅传递已勾选复选框的曲目 ID、专辑编号和曲目编号。用于插入“trackconnections”表。

相反,它仅缩小勾选的复选框轨道 ID ,然后为每个可用轨道创建逗号分隔值以供选择,而不仅仅是那些实际选择的轨道。

在将数据从表单传递到包含时,这会导致烦人的输出,例如:

albumid: 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
trackid: 30,14
albumtracknum: ,2,3,,,,,,,,,,,,,,,,,,,,,

它应该只读作:

albumid: 4,4
trackid: 30,14
albumtracknum: 2,3

有太多的数据通过意味着一旦我完成这项工作,在多个 INSERTS 上的行插入将不正确,因为它们不会以正确的顺序相互对齐。

2. 在“trackconnections”表中只包含 INSERTS 1 行。

看来我误解了如何在这里使用我的代码向数据库添加多行。

由于在我的“将现有曲目附加到专辑”表单上勾选了多个复选框,因此每次提交表单时只会在数据库中插入 1 行。

一直以来,添加到“trackconnections”表中的唯一曲目是第一个选中其复选框的曲目,并且由于问题编号。在上面的 1 中,albumtracknum始终为 0,除非我在可用清单上的第一个albumtracknum框中键入一个数字。

我需要对此代码进行调整,以便同时解决问题 1 和 2,这意味着勾选复选框并将曲目编号添加到曲目名称后面的每个框中实际上会在数据库中添加多行以及相应的专辑曲目编号。

我希望有人能帮帮忙。

编辑以显示精炼和工作代码:

复选框和文本框部分的新代码 -

if (isset($_POST['attachexistingtracktoalbum-submit'])) {
    
require "includes/db_connect.pdo.php";

$artistid = $_POST["artistid"];
$albumid = $_POST["albumid"];

echo '<strong>Select each track you would like to add to this album below and type in the track number you want it to have on the album in the box underneith the name of each selected track.</strong><br><br>';

$stmt = $pdo->query("SELECT * FROM track WHERE artist_id = '$artistid'
order by trackname");

echo '<form action="includes/attachexistingtracktoalbum.inc.php" method = "post">';

while ($row = $stmt->fetch())
{           
    
    echo '<div class="checkbox">';
    echo '<label>';
    echo "<input type='checkbox' name='trackid[]' value='".$row['id']."' />";
        echo '<span class="cr"><i class="cr-icon glyphicon glyphicon-ok"></i></span>';
    echo ' '.$row['trackname'];
    echo '</label>';
    echo "<br><label for='albumtracknumber'>Track number:</label><br>
    <input type='text' name='albumtracknumber_".$row['id']."'>
    <input type='hidden' name='albumid[]' value='".$albumid,"'>
    <br><br>";
    echo '</div>';

}
?>
  <input type="hidden" name="albumidforreturn" value="<?php echo $albumid;?>">
  <button type="submit" name="attachexistingtracktoalbum-submit">Attach track(s) to album</button>
  </form>
  
<?php }
else {
header("Location: /index.php");
 exit();
}

包含 INSERT 处理的新代码 -

    if (isset($_POST['attachexistingtracktoalbum-submit'])) {

    require "db_connect.pdo.php";
     
     $albumid = implode(',',$_POST['albumid']);
     $trackid  = implode(',',$_POST['trackid']);
     $albumidforreturn = $_POST['albumidforreturn'];
     
foreach($_POST['trackid'] as $trackidloop) {
    
$albumtracknum = $_POST["albumtracknumber_{$trackidloop}"];

$sql = "INSERT INTO trackconnections (albumid, trackid, albumtracknum) VALUES (?,?,?);";
      $stmt= $pdo->prepare($sql);
      $stmt->execute([$albumid,$trackidloop,$albumtracknum]);
}
        header("Location: ../albumdetail.php?albumid=$albumidforreturn");
        exit();
    }
    else {
    header("Location: ../index.php");
     exit();
    }

标签: phpmysqlinsert

解决方案


这不是一个完整的解决方案,但我看到了一些问题:您正在循环播放曲目并为每个曲目创建一个新表单。第一个问题是,您缺少结束表单标记。我猜当浏览器看到下一个表单开始标签时,它会自动创建一个。?? 这就是为什么您只会得到一个已发布的复选框。我会将所有轨道复选框放入一个表单中。然后发布的 trackid[] 数组将包含所有选中的项目。

[在您发表评论后进行编辑:隐藏字段 albumid[] 发布整个数组,而 trackid[] 复选框仅发布实际选中的框(HTML 规范)。

您可以将 trackID 和 albumID 放在一起作为复选框值,而不是使用 albumid[],然后在处理帖子时将它们分开: $value = $row['id']. ',' . $row['albumid']; echo "<input type='checkbox' name='trackid[]' value='".$value."' />";

此外,SQL“INSERT INTO (..) .. VALUES (...)”只插入一行。
对于所有选中的框,在循环中执行该 SQL 很容易。
foreach($_POST['trackid'] as $value) { // parse the $value... // SQL Insert... }

编辑2:来自我自己的评论:像隐藏字段一样,输入(文本)字段数组也发布整个数组(空白输入为空值)。(同样,这不是 PHP 的东西,它是一个 Web 浏览器标准,只发布选中的复选框和单选按钮。但所有文本和隐藏的 INPUT 都会发布。)所以在你的例子中,你需要编写一个机制来知道哪个文本框去每个复选框。快速而肮脏...您可以在复选框值中添加一个行索引 (0,1,2,3...) 作为另一个逗号分隔的数字,然后您将索引放入已发布的文本框数组中。或者,您可以命名文本框' .. name="textinput_' . $row['trackid'] . '" ...'(不是数组),然后在发布后,在您的 foreach 循环中读取它们
$val = $_POST["textinput_{$trackid}"];


推荐阅读