Home > Blockchain >  Update MySQL Database With Data From Multiple Input Elements Inside A While Loop, And A Single Submi
Update MySQL Database With Data From Multiple Input Elements Inside A While Loop, And A Single Submi

Time:12-27

I have a page that fetches images from a database after an initial upload, that allows the user to add titles and tags to the images.

I have set the while loop to output the individual images inside one form. Each image has two related input fields. What I would like to do is have it so when the form is submitted all of the information is updated in the database in one go (even if image details from the relevant input fields remain blank/are not filled in).

To achieve this I thought I could have the form’s submit button outside of the while loop. This isn’t working as foreseen though. It basically updates one image at a time, each time I press submit (it updates the last image in the loop).

How do I get it so it processes all of the information for all of the images inside the while loop in one go, on submit? If I place the submit button inside the loop I get a button for every image, which I don't want.

Note: the <img/> source path I've just hardcoded below to save adding the different variables that achieve this, thus hopefully keeping the code simpler.

Fetch data from database and output HMTL form

<?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 >                
        <div >
            <img src="/project/images/image.jpg">
        </div>
        <div >
            <div >
                <label for="upload-details-title">Image Title</label>
                <input id="upload-details-title" type="text" name="image-title">
            </div>
            <div >
                <label for="upload-details-tags">Comma Separated Image Tags</label>
                <textarea id="upload-details-tags" type="text" name="image-tags"></textarea>
            </div>
            <div >
                <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>

Update Database On Form submission

<?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 = "";

}

?>

CodePudding user response:

The problem with your current approach is that bcs each set of inputs uses the same name, they overwrite each other. Say you have 3 records, 3 sets of form inputs on your front end. If you enter for image-title values of one, two, and three, on the back-end you'll only ever see three.

You can verify this yourself: print_r($_POST);.

The solution is to send the data as arrays, and you can do this by simply using [] in your input names:

<?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>

Now you'll get arrays of input on the back end, like (again, use print_r($_POST); to see for yourself):

[image-title] => Array
    (
        [0] => First Title
        [1] => 2nd Title
    )

[image-tags] => Array
    (
        [0] => foo
        [1] => bar
    )

[image-filename] => Array
    (
        [0] => filename
        [1] => another-filename
    )

And so you can loop through them, processing them one at a time:

$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]
    ]);
}

Note that using the filename as the unique identifier is probably not ideal - that's what IDs are for. Your DB queries will be much more efficient for queries like UPDATE ... WHERE id=:id. You can do that by replacing your hidden file input with a hidden ID input (assuming your primary key is id):

<input type="hidden" name="id[]" value="<?php echo $row->id; ?>">

And then of course on the back end update your query:

WHERE id = :id
// ...
':id'    => $_POST['id'][$key]

As you can imagine this is a common problem, and there are many other solutions here to reference:

PHP docs reference:

CodePudding user response:

If I understand your question correctly, you want all of the multiple input entries to be saved to your db for each image.

To do this, you will first of all need to make each input name an array. For example, on your first input, "image-title" you would need to make it "image-title[]". You'll also need "image-tags" to be "image-tags[]".

Once you have that completed, you will need logic in the code it submits to, to loop through each of the inputs and update the database.

So now $image_title on the submit script will be an array of the values. You need to loop through those and update the database accordingly.

  • Related