0

Having a table generated from MySQL datas, each row has a field containing multiple forms.

I need to put a checkbox on the first field of each row, containing the unique ID, and later I need to pass the multiple checkbox values by POST with a button located outside the table.

How do I obtain that, when nested forms cannot be done?

Here's my code:

    <!-- This button needs to be outside of the table -->
    <button type="submit" form="selected_checkboxes">Send checked boxes</button>

    <table>
    <thead>
    <tr>
    <th>Select</th>
    <th>Name</th>
    <th>Action</th>
    </tr>
    </thead>
    <tbody>

    <!-- If I put the form there, for the selected checkbox, it won't work, because the other forms
    are nested inside the table -->
    <form action="page.php" method="POST" name="selected_checkboxes">  <!-- THIS WON'T WORK -->

    <?php
    $db = $conn->prepare('SELECT * FROM accounts WHERE name = ? ORDER BY id DESC');
    $db->bind_param('i', $name);
    if (!$db->execute()) die('Error while fetching accounts: '. $conn->error);
    $res = $db->get_result();
    while ($data = $res->fetch_assoc()) {
        $id = $data['id'];
        $name = $data['name'];
        echo '<tr>
        <td><input type="checkbox" name="list[]" value="'.$id.'"></td>
        <td>'.$name.'</td>
        <td>
            <form action="page.php" method="POST"><input type="hidden" name="id" value="'.$id.'" /><button type="submit" name="action1">Send</button></form>
            <form action="page.php" method="POST"><input type="hidden" name="id" value="'.$id.'" /><button type="submit" name="action2">Archive</button></form>
        </td>
        </tr>
    }
    ?>
    
    </form>  <!-- TO CLOSE THE NOT WORKING FORM -->
    </tbody>
    </table>

How would you solve this problem?

Dharman
  • 30,962
  • 25
  • 85
  • 135
  • It is a very bad idea to use `die(mysqli_error($$conn));` in your code, because it could potentially leak sensitive information. See this post for more explanation: [mysqli or die, does it have to die?](https://stackoverflow.com/a/15320411/1839439) – Dharman Dec 29 '20 at 21:56
  • @Dharman I appreciate it, but it's a personal project, so I don't really look at that, but thanks – Ferdinando Di Lauro Dec 29 '20 at 21:58
  • Since they all go to the same place, just use the outer form and test for the individual actions ($action1, $action2) – Tim Morton Dec 29 '20 at 21:59
  • 1
    Why? Why would you ignore my advice to make your code simpler and better? If you are only learning PHP then please start by learning the easiest solutions. Don't overcomplicate it. – Dharman Dec 29 '20 at 21:59
  • @Dharman it's not about make it simpler or better, since it's personal project, nobody will ever even see it – Ferdinando Di Lauro Dec 29 '20 at 22:01
  • @TimMorton Them goes to same place, but, each row has different IDs and datas that has to be transferred through the Action column, that is the one giving me struggle – Ferdinando Di Lauro Dec 29 '20 at 22:03
  • working on an answer, but I see you already accepted an answer. If you want to consider a different route, let me know. – Tim Morton Dec 29 '20 at 22:23

2 Answers2

0
<td>
    <form action="page.php" method="POST"><input type="hidden" name="id" value="'.$id.'" />
    <button type="submit" name="action1">Send</button>
    </form>
    <form action="page.php" method="POST"><input type="hidden" name="id" value="'.$id.'" />
    <button type="submit" name="action2">Archive</button>
    </form>
    </td>

in this section I would modify it with hotlinks instead of forms and make diffrent handling page, for example:

echo "<td><a href='page2.php?action=send&id=".$id."'>Send</a> ";
echo "<a href='page2.php?action=archive&id=".$id."'>Send</a></td>";

and the page2.php would operate on $_GET["action"] and $_GET["id"] like replaced mini-form.

then your form from the begining (with checkboxes, that you stated that doesn't work) will be the only one and work :) this will be ok only if you gave access to verified user.

hope this will push you foreward.

:)

0

Assuming that you are actually manipulating the data and not simply requesting a view, POST is the appropriate verb to use.

You can simply index the submit buttons with the id of the selected item. I have put your script into a standard format of working with potential user input (assuming this script is page.php) and then displaying the form:

<?php
// get $conn and other config

if(!empty($_POST['selected_checkboxes']) {
    // iterate through $_POST['id_list']
    header(location: '/page/to/show/on/completion');
    exit;
}

if(!empty($_POST['send']) {
    $arr = (array)$_POST['send'];
    $id = array_keys($arr)[0];
    // do what you need to do with the id
    header(location: '/page/to/show/on/completion');
    exit;
}

if(!empty($_POST['archive']) {
    $arr = (array)$_POST['archive'];
    $id = array_keys($arr)[0];
    // do what you need to do with the id
    header(location: '/page/to/show/on/completion');
    exit;
}
$db = $conn->prepare('SELECT * FROM accounts WHERE name = ? ORDER BY id DESC');
$db->bind_param('i', $name);
$accountList = $db->get_result();
?>
<html>
...
<form action="page.php" method="POST">
    <button type="submit" name="selected_checkboxes">Send checked boxes</button>
    <table>
        <thead>
            <tr>
                <th>Select</th>
                <th>Name</th>
                <th>Action</th>
            </tr>
        </thead>
        <tbody>
        <?php while($data = $accountList->fetch_assoc()): ?>
            <tr>
                <td><input type="checkbox" name="id_list[]" value="<?= $data['id'] ?>"></td>
                <td><?= $data['name'] ?></td>
                <td>
                    <button type="submit" name="send[<?= $data['id'] ?>]">Send</button>
                    <button type="submit" name="archive[<?= $data['id'] ?>]">Archive</button>
                </td>
            </tr>
        <?php endwhile; ?>
        </tbody>
    </table>
</form>  
Tim Morton
  • 2,614
  • 1
  • 15
  • 23