使用来自 While 循环内的多个输入元素的数据以及来自 While 循环外的单个提交按钮的数据更新 MySQL 数据库
Update MySQL Database With Data From Multiple Input Elements Inside A While Loop, And A Single Submit Button Outside of The While Loop
我有一个页面可以在初始上传后从数据库中获取图像,允许用户为图像添加标题和标签。
我已经设置了 while
循环以在一个表单中输出单个图像。每个图像都有两个相关的输入字段。我想做的是拥有它,以便在提交表单时一次性更新数据库中的所有信息(即使相关输入字段中的图像详细信息仍然 blank/are 未填写)。
为了实现这一点,我想我可以在 while
循环之外设置表单的提交按钮。但这并没有像预期的那样工作。它基本上一次更新一张图像,每次我按下提交(它更新循环中的最后一张图像)。
我如何获取它以便在提交时一次性处理 while 循环内所有图像的所有信息?如果我将提交按钮放在循环内,我会为每张图片获得一个按钮,这是我不想要的。
注意: <img/>
源路径我刚刚在下面进行了硬编码,以节省添加实现此目的的不同变量,从而希望使代码更简单。
从数据库中获取数据并输出HMTL格式
<?php isset($_REQUEST['username']) ? $username = $_REQUEST['username'] : header("Location: login.php"); ?>
<form method="post" enctype="multipart/form-data">
<?php
if (isset($_SESSION['logged_in'])) {
$user_id = $_SESSION['logged_in'];
}
$stmt = $connection->prepare("SELECT * FROM lj_imageposts WHERE user_id = :user_id");
$stmt->execute([
':user_id' => $user_id
]);
while ($row = $stmt->fetch()) {
$db_image_filename = htmlspecialchars($row['filename']);
?>
<div class="upload-details-component">
<div class="form-row">
<img src="/project/images/image.jpg">
</div>
<div class="edit-zone">
<div class="form-row">
<label for="upload-details-title">Image Title</label>
<input id="upload-details-title" type="text" name="image-title">
</div>
<div class="form-row">
<label for="upload-details-tags">Comma Separated Image Tags</label>
<textarea id="upload-details-tags" type="text" name="image-tags"></textarea>
</div>
<div class="form-row">
<input type="hidden" name="username" value="<?php echo $username; ?>">
<input type="hidden" name="image-filename" value="<?php echo $db_image_filename; ?>">
</div>
</div>
</div>
<?php } ?>
<button type="submit" name="upload-submit">COMPLETE UPLOAD</button>
</form>
在提交表单时更新数据库
<?php
if(isset($_POST['upload-submit'])) {
$image_title = $_POST['image-title'];
$image_tags = $_POST['image-tags'];
$form_filename = $_POST['image-filename']; // value attribute from hidden form element
try {
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE filename = :filename";
$stmt = $connection->prepare($sql);
$stmt->execute([
':image_title' => $image_title,
':image_tags' => $image_tags,
':filename' => $form_filename
]);
// This is the URL to this actual page (basically refreshes the page)
header("Location: upload-details.php?username={$username}");
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
// give values an empty string to avoid an error being thrown before form submission if empty
$image_title = $image_tags = "";
}
?>
如果我对你的问题的理解正确,你希望将每张图像的所有多个输入条目保存到你的数据库中。
为此,您首先需要将每个输入名称设为一个数组。例如,在您的第一个输入“image-title”中,您需要将其设为“image-title[]”。您还需要将“image-tags”设为“image-tags[]”。
完成后,您需要在其提交的代码中添加逻辑,以遍历每个输入并更新数据库。
现在提交脚本上的 $image_title 将是一个值数组。您需要遍历这些并相应地更新数据库。
您当前方法的问题是 bcs 每组输入使用相同的 name
,它们相互覆盖。假设您有 3 条记录,前端有 3 组表单输入。如果您输入 one
、two
和 three
的 image-title
值,在后端您只会看到 three
.
你可以自己验证一下:print_r($_POST);
.
解决方案是将数据作为数组发送,您只需在输入名称中使用 []
即可:
<?php while ($row = $stmt->fetch()) { ?>
<input type="text" name="image-title[]">
<textarea type="text" name="image-tags[]"></textarea>
<input type="hidden" name="image-filename[]" value="<?php echo $db_image_filename; ?>">
<?php } ?>
<button type="submit" name="upload-submit">COMPLETE UPLOAD</button>
现在您将在后端获得输入数组,例如(再次使用 print_r($_POST);
亲自查看):
[image-title] => Array
(
[0] => First Title
[1] => 2nd Title
)
[image-tags] => Array
(
[0] => foo
[1] => bar
)
[image-filename] => Array
(
[0] => filename
[1] => another-filename
)
因此您可以遍历它们,一次处理一个:
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE filename = :filename";
$stmt = $connection->prepare($sql);
foreach ($_POST['image-title'] as $key => $value) {
$stmt->execute([
':image_title' => $_POST['image-title'][$key],
':image_tags' => $_POST['image-tags'][$key],
':filename' => $_POST['image-filename'][$key]
]);
}
请注意,使用文件名作为唯一标识符并不理想 - 这就是 ID 的用途。存在非唯一文件名的潜在风险,但您的数据库查询对于类似(假设您的 table 有一个主键 id
)UPDATE ... WHERE id=:id
的查询也会更有效。您可以通过将隐藏文件输入替换为隐藏 ID 输入来做到这一点:
<input type="hidden" name="id[]" value="<?php echo $row->id; ?>">
然后当然在后端更新您的查询:
WHERE id = :id
// ...
':id' => $_POST['id'][$key]
更好的是,您可以在输入 name
中使用 id
来显式标识值集:
<input type="text" name="image-title[<?php echo $row->id; ?>]">
<textarea type="text" name="image-tags[<?php echo $row->id; ?>]"></textarea>
在这种情况下,您甚至不需要将 id
(或 image-filename
)作为单独的隐藏输入传递 - 您已经在输入名称中包含了所有 ID。在后端你可以这样做:
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE id = :id";
$stmt = $connection->prepare($sql);
foreach ($_POST['image-title'] as $id => $value) {
$stmt->execute([
':image_title' => $_POST['image-title'][$id],
':image_tags' => $_POST['image-tags'][$id],
':id' => $id
]);
}
你可以想象这是一个普遍的问题,这里还有很多其他的解决方案可供参考:
- Multiple inputs with same name through POST in php
- How to get a form input array into a PHP array
- HTML/PHP - Form - Input as array
PHP 文档参考:
首先,在您的 question/code 中,您使用 filename
字段作为您在 table lj_imageposts
中记录的唯一标识符。我假设您确定此字段中的值对于您拥有的每个用户都是唯一的。我强烈建议您在 table 中创建一个唯一的自动递增字段 id
(以防万一您没有)并使用它。在我的回答中,我将使用 id
字段来识别图像。
while ($row = $stmt->fetch()) {
$db_image_id = $row['id']; // the unique id for this image
$db_image_filename = htmlspecialchars($row['filename']);
...
...
其次,当您 create/build 您的表单时,为您的输入使用数组名称,并确保您拥有的每张图像都有一个唯一的输入名称。为此替换名称:
<input id="upload-details-title" type="text" name="image-title">
对此:
<input id="upload-details-title_<?=$db_image_id;?>" type="text" name="image-title[<?=$db_image_id;?>]">
重要 您需要为循环中的每个 input
和 textarea
执行此操作。
此时,当您提交表单时,您的 $_POST
应该看起来像这样
array(
'image-title' => array(
1 => 'First Image Title',
2 => 'Second Image Title',
3 => 'Third Image Title',
...
...
),
'image-tags' => array(
1 => 'First Image Tags',
2 => 'Second Image Tags',
3 => 'Third Image Tags',
...
...
),
...
...
)
其中 1、2、3... 是您的图片的 ID
第三,在你的更新代码中,你需要循环你有数据的图像,并一张一张地更新图像:
if(isset($_POST['upload-submit'])) {
foreach( $_POST['image-title'] as $image_id => $dummy) { // at this point I only need the ID
$image_title = $_POST['image-title'][$image_id];
$image_tags = $_POST['image-tags'][$image_id];
// I don't need this value to identify the record. in this example I'm using `id` field
//$form_filename = $_POST['image-filename'][$imageId]; // value attribute from hidden form element
try {
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE id = :id";
$stmt = $connection->prepare($sql);
$stmt->execute([
':image_title' => $image_title,
':image_tags' => $image_tags,
':id' => $image_id // using id instead of filename as identifier
]);
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
// move the "redirect" header to outside my update loop
// This is the URL to this actual page (basically refreshes the page)
header("Location: upload-details.php?username={$username}");
// also, exit to only send the redirect header not anything else
exit;
}
我有一个页面可以在初始上传后从数据库中获取图像,允许用户为图像添加标题和标签。
我已经设置了 while
循环以在一个表单中输出单个图像。每个图像都有两个相关的输入字段。我想做的是拥有它,以便在提交表单时一次性更新数据库中的所有信息(即使相关输入字段中的图像详细信息仍然 blank/are 未填写)。
为了实现这一点,我想我可以在 while
循环之外设置表单的提交按钮。但这并没有像预期的那样工作。它基本上一次更新一张图像,每次我按下提交(它更新循环中的最后一张图像)。
我如何获取它以便在提交时一次性处理 while 循环内所有图像的所有信息?如果我将提交按钮放在循环内,我会为每张图片获得一个按钮,这是我不想要的。
注意: <img/>
源路径我刚刚在下面进行了硬编码,以节省添加实现此目的的不同变量,从而希望使代码更简单。
从数据库中获取数据并输出HMTL格式
<?php isset($_REQUEST['username']) ? $username = $_REQUEST['username'] : header("Location: login.php"); ?>
<form method="post" enctype="multipart/form-data">
<?php
if (isset($_SESSION['logged_in'])) {
$user_id = $_SESSION['logged_in'];
}
$stmt = $connection->prepare("SELECT * FROM lj_imageposts WHERE user_id = :user_id");
$stmt->execute([
':user_id' => $user_id
]);
while ($row = $stmt->fetch()) {
$db_image_filename = htmlspecialchars($row['filename']);
?>
<div class="upload-details-component">
<div class="form-row">
<img src="/project/images/image.jpg">
</div>
<div class="edit-zone">
<div class="form-row">
<label for="upload-details-title">Image Title</label>
<input id="upload-details-title" type="text" name="image-title">
</div>
<div class="form-row">
<label for="upload-details-tags">Comma Separated Image Tags</label>
<textarea id="upload-details-tags" type="text" name="image-tags"></textarea>
</div>
<div class="form-row">
<input type="hidden" name="username" value="<?php echo $username; ?>">
<input type="hidden" name="image-filename" value="<?php echo $db_image_filename; ?>">
</div>
</div>
</div>
<?php } ?>
<button type="submit" name="upload-submit">COMPLETE UPLOAD</button>
</form>
在提交表单时更新数据库
<?php
if(isset($_POST['upload-submit'])) {
$image_title = $_POST['image-title'];
$image_tags = $_POST['image-tags'];
$form_filename = $_POST['image-filename']; // value attribute from hidden form element
try {
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE filename = :filename";
$stmt = $connection->prepare($sql);
$stmt->execute([
':image_title' => $image_title,
':image_tags' => $image_tags,
':filename' => $form_filename
]);
// This is the URL to this actual page (basically refreshes the page)
header("Location: upload-details.php?username={$username}");
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
// give values an empty string to avoid an error being thrown before form submission if empty
$image_title = $image_tags = "";
}
?>
如果我对你的问题的理解正确,你希望将每张图像的所有多个输入条目保存到你的数据库中。
为此,您首先需要将每个输入名称设为一个数组。例如,在您的第一个输入“image-title”中,您需要将其设为“image-title[]”。您还需要将“image-tags”设为“image-tags[]”。
完成后,您需要在其提交的代码中添加逻辑,以遍历每个输入并更新数据库。
现在提交脚本上的 $image_title 将是一个值数组。您需要遍历这些并相应地更新数据库。
您当前方法的问题是 bcs 每组输入使用相同的 name
,它们相互覆盖。假设您有 3 条记录,前端有 3 组表单输入。如果您输入 one
、two
和 three
的 image-title
值,在后端您只会看到 three
.
你可以自己验证一下:print_r($_POST);
.
解决方案是将数据作为数组发送,您只需在输入名称中使用 []
即可:
<?php while ($row = $stmt->fetch()) { ?>
<input type="text" name="image-title[]">
<textarea type="text" name="image-tags[]"></textarea>
<input type="hidden" name="image-filename[]" value="<?php echo $db_image_filename; ?>">
<?php } ?>
<button type="submit" name="upload-submit">COMPLETE UPLOAD</button>
现在您将在后端获得输入数组,例如(再次使用 print_r($_POST);
亲自查看):
[image-title] => Array
(
[0] => First Title
[1] => 2nd Title
)
[image-tags] => Array
(
[0] => foo
[1] => bar
)
[image-filename] => Array
(
[0] => filename
[1] => another-filename
)
因此您可以遍历它们,一次处理一个:
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE filename = :filename";
$stmt = $connection->prepare($sql);
foreach ($_POST['image-title'] as $key => $value) {
$stmt->execute([
':image_title' => $_POST['image-title'][$key],
':image_tags' => $_POST['image-tags'][$key],
':filename' => $_POST['image-filename'][$key]
]);
}
请注意,使用文件名作为唯一标识符并不理想 - 这就是 ID 的用途。存在非唯一文件名的潜在风险,但您的数据库查询对于类似(假设您的 table 有一个主键 id
)UPDATE ... WHERE id=:id
的查询也会更有效。您可以通过将隐藏文件输入替换为隐藏 ID 输入来做到这一点:
<input type="hidden" name="id[]" value="<?php echo $row->id; ?>">
然后当然在后端更新您的查询:
WHERE id = :id
// ...
':id' => $_POST['id'][$key]
更好的是,您可以在输入 name
中使用 id
来显式标识值集:
<input type="text" name="image-title[<?php echo $row->id; ?>]">
<textarea type="text" name="image-tags[<?php echo $row->id; ?>]"></textarea>
在这种情况下,您甚至不需要将 id
(或 image-filename
)作为单独的隐藏输入传递 - 您已经在输入名称中包含了所有 ID。在后端你可以这样做:
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE id = :id";
$stmt = $connection->prepare($sql);
foreach ($_POST['image-title'] as $id => $value) {
$stmt->execute([
':image_title' => $_POST['image-title'][$id],
':image_tags' => $_POST['image-tags'][$id],
':id' => $id
]);
}
你可以想象这是一个普遍的问题,这里还有很多其他的解决方案可供参考:
- Multiple inputs with same name through POST in php
- How to get a form input array into a PHP array
- HTML/PHP - Form - Input as array
PHP 文档参考:
首先,在您的 question/code 中,您使用 filename
字段作为您在 table lj_imageposts
中记录的唯一标识符。我假设您确定此字段中的值对于您拥有的每个用户都是唯一的。我强烈建议您在 table 中创建一个唯一的自动递增字段 id
(以防万一您没有)并使用它。在我的回答中,我将使用 id
字段来识别图像。
while ($row = $stmt->fetch()) {
$db_image_id = $row['id']; // the unique id for this image
$db_image_filename = htmlspecialchars($row['filename']);
...
...
其次,当您 create/build 您的表单时,为您的输入使用数组名称,并确保您拥有的每张图像都有一个唯一的输入名称。为此替换名称:
<input id="upload-details-title" type="text" name="image-title">
对此:
<input id="upload-details-title_<?=$db_image_id;?>" type="text" name="image-title[<?=$db_image_id;?>]">
重要 您需要为循环中的每个 input
和 textarea
执行此操作。
此时,当您提交表单时,您的 $_POST
应该看起来像这样
array(
'image-title' => array(
1 => 'First Image Title',
2 => 'Second Image Title',
3 => 'Third Image Title',
...
...
),
'image-tags' => array(
1 => 'First Image Tags',
2 => 'Second Image Tags',
3 => 'Third Image Tags',
...
...
),
...
...
)
其中 1、2、3... 是您的图片的 ID
第三,在你的更新代码中,你需要循环你有数据的图像,并一张一张地更新图像:
if(isset($_POST['upload-submit'])) {
foreach( $_POST['image-title'] as $image_id => $dummy) { // at this point I only need the ID
$image_title = $_POST['image-title'][$image_id];
$image_tags = $_POST['image-tags'][$image_id];
// I don't need this value to identify the record. in this example I'm using `id` field
//$form_filename = $_POST['image-filename'][$imageId]; // value attribute from hidden form element
try {
$sql = "UPDATE lj_imageposts SET
image_title = :image_title,
image_tags = :image_tags
WHERE id = :id";
$stmt = $connection->prepare($sql);
$stmt->execute([
':image_title' => $image_title,
':image_tags' => $image_tags,
':id' => $image_id // using id instead of filename as identifier
]);
} catch (PDOException $e) {
echo "Error: " . $e->getMessage();
}
}
// move the "redirect" header to outside my update loop
// This is the URL to this actual page (basically refreshes the page)
header("Location: upload-details.php?username={$username}");
// also, exit to only send the redirect header not anything else
exit;
}