-1

I created a table in mySQL that contains fields such as "name" etc, and I dynamically created several divs (containing a form and a button) relative to how many rows are in that table.

It looks like this :

<?php if ($tabLength > 0) {
      for ($x = 0; $x < $tabLength; $x++) {
        echo "<div class='data'>
                <ul class='data__list bg-grey'>
                <li class='data__item name-value'>" . $tab[$x][1] . "</li>
                <li class='data__item'>
                  <div class='data-modifiers'>
                    <form action='../extern/delete.ext.php' method='post'>
                      <input type='hidden' name='" . $tab[$x][1] . "' />
                      <button type='submit' name='delete-submit' class='btn btn-link'>Delete</button>
                    </form>
                  </div>
                </li>
              </ul>
            </div>";
      }
    }

Now I want that when I click the "Delete" button it delete specifically that div.

Thing is, since the inputs's "name" attributes are created dynamically (and which end up being "Bob", "Frank" and whatever for each div's input) I don't know how to use $_POST on the "delete.ext.php file.

Here's my code in delete.ext.php :

<?php
session_start();

if (isset($_POST["delete-submit"])) {
  require "dbh.ext.php";

  $name = $_POST[' --- what to put in here ? ---']

  $sql = "DELETE FROM persons WHERE name='" . $name . "';";
  $res = mysqli_query($conn, $sql);

  if (!$res) {
    header("Location: ../persons/persons.php?error=sqlerror");
    exit();
  } else {
    header("Location: ../persons/persons.php");
    exit();
  }
}

So, for example, if the "Delete" button I'm clicking on is in the div which contains an input with a dynamically created "name" attribut of "Frank", what should I pass in $_POST to effectively delete specifically that row from the mySQL table ?

Thanks !


Code update :

<?php if ($tabLength > 0) {
      for ($x = 0; $x < $tabLength; $x++) {
        echo "<div class='data'>
                <ul class='data__list bg-grey'>
                <li class='data__item name-value'>" . $tab[$x][1] . "</li>
                <li class='data__item'>
                  <div class='data-modifiers'>
                    <form action='../extern/delete.ext.php' 
 method='post'>
                      <input type='hidden' name='name' value='" . $tab[$x][1] . "' />
                      <button type='submit' name='delete-submit' class='btn btn-link'>Delete</button>
                    </form>
                  </div>
                </li>
              </ul>
            </div>";
      }
    }

And :

    <?php
    session_start();
    if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST["delete- 
    submit"])) 
    {
    require "dbh.ext.php";
    $sql = "DELETE FROM persons WHERE name= ?";
    $stmt = $conn->prepare($sql);
    $stmt->bind_param('s', $_POST['name']);
    $res = $stmt->execute();

    if (!$res) {
        header("Location: ../persons/persons.php?error=sqlerror");
        exit;
    } else {
        header("Location: ../persons/persons.php");
        exit();
    }
}

this is what's in dbh.ext.php

<?php 
$servername = "localhost"; 
$dBUsername = "root"; 
$dBPassword = ""; 
$dBName = "ruchesdb"; 
$conn = mysqli_connect($servername, $dBUsername, $dBPassword, $dBName); 
if(!$conn) { 
    die("Connection failed".mysqli_connect_error()); 
} 
RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
  • 1
    Why not dump `$_POST` to see what it contains? Also, why do you need to use distinct names for that field? Why not use the exact same name, but different values? – Nico Haase Jun 30 '21 at 12:19
  • 1
    Also, your `DELETE` query is widely open for SQL injection. Better have a look at prepared statements – Nico Haase Jun 30 '21 at 12:20
  • I'm okay with using the same name but different values, but again, how can I delete the row which name's value is said value ? – Benjamin A Jun 30 '21 at 12:24
  • By using a `DELETE` query? Anything wrong with that? – Nico Haase Jun 30 '21 at 12:25
  • But I am using a DELETE query. But I don't know how to check for the value I want for the name – Benjamin A Jun 30 '21 at 12:26
  • I should also note that `if (isset($_POST["delete-submit"]))` is prone to failure as the submit button itself might not get submitted. If I were you, I'd look into AJAX and try to submit just the data you're looking for – Machavity Jun 30 '21 at 12:28
  • Why don't you know how to do that? Maybe because you are still using different names for the field, instead of **everytime the same name** with different values? – Nico Haase Jun 30 '21 at 12:28
  • What he means is that you're concatenating *user supplied data* into your SQL. If you [use prepared statements](https://stackoverflow.com/a/60496/2370483) you avoid anything bad they might submit. – Machavity Jun 30 '21 at 12:29

1 Answers1

2

Instead of placing some data in a name attribute, make the name attribute something you know and use the value attribute the unknown data, the name in this case.

So

<input type='hidden' name='" . $tab[$x][1] . "' />

becomes

<input type='hidden' name="thename" value='" . $tab[$x][1] . "' />

Now in the PHP you know what to look for. So all we need to fix now is the SQL Injection Attack issues, we do that by preparing the query with a parameter and then binding a value to the parameter like this

<?php
session_start();

if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST["delete-submit"])) 
{
    require "dbh.ext.php";

    // add a parameter to the query and not a concatenated value        
    $sql = "DELETE FROM `persons` WHERE `name` = ?";

    $stmt = $conn->prepare($sql);
    
    // bind the value to the parameter
    $stmt->bind_param('s', $_POST['thename']);
    $res = $stmt->execute();

    if (!$res) {
        header("Location: ../persons/persons.php?error=sqlerror");
        exit;
    } else {
        header("Location: ../persons/persons.php");
        exit();
    }
}
RiggsFolly
  • 93,638
  • 21
  • 103
  • 149
  • Thanks for you answer. Before using your fix for the SQL Injection Attack issues, it was working. But now that I have applied it, I get that error : Fatal error: Uncaught ArgumentCountError: The number of variables must match the number of parameters in the prepared statement in C:\xampp\htdocs\src\extern\delete.ext.php:10 Stack trace: #0 C:\xampp\htdocs\src\extern\delete.ext.php(10): mysqli_stmt->bind_param('s', 'Frank') #1 {main} thrown in C:\xampp\htdocs\src\extern\delete.ext.php on line 10 Can you help ? Thanks ! – Benjamin A Jun 30 '21 at 12:36
  • 1
    Btw., this does not really need a hidden field - `button` itself has a `value` attribute, too. – CBroe Jun 30 '21 at 12:37
  • Guess - you didnt change the raw SQL to have a `?` in place of the variable you originally had – RiggsFolly Jun 30 '21 at 12:41
  • @CBroe True, didn't want to change too much all in one go for someone who is obviously still learning, and ..... I didnt think of that :) – RiggsFolly Jun 30 '21 at 12:42
  • No I put the right one – Benjamin A Jun 30 '21 at 12:42
  • Better show the new code then, add it to your question – RiggsFolly Jun 30 '21 at 12:44
  • I just did it :) – Benjamin A Jun 30 '21 at 12:47
  • 2
    Like I guessed .... `$sql = "DELETE FROM persons WHERE name='" . $name . "';";` **Is not** what I coded in my answer :) – RiggsFolly Jun 30 '21 at 12:48
  • 1
    _“No I put the right one”_ - only it _isn’t_ the “right one”, when you want to use prepared statements correctly, with placeholders. – CBroe Jun 30 '21 at 12:50
  • I fixed it, because indeed I thought I got it right, but clearly didn't. Now it still doesn't work but the error is different : Fatal error: Uncaught Error: Call to a member function bind_param() on bool in C:\xampp\htdocs\src\extern\delete.ext.php:10 Stack trace: #0 {main} thrown in C:\xampp\htdocs\src\extern\delete.ext.php on line 10 – Benjamin A Jun 30 '21 at 12:57
  • That usually means that the prepare() failed! So that means the query is probably wrong in some way. Looks simple enough, so lets add these 4 lines to the top of the script you want to debug `ini_set('display_errors', 1); ini_set('log_errors',1); error_reporting(E_ALL); mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);`. This will force any `MYSQLI_` errors to generate an Exception that you can see on the browser as well as normal PHP errors. – RiggsFolly Jun 30 '21 at 13:02
  • Maybe we should also check whats in `dbh.ext.php` – RiggsFolly Jun 30 '21 at 13:06
  • this is what's in dbh.ext.php : prepare('DELETE FROM per...') #1 {main} thrown in C:\xampp\.. – Benjamin A Jun 30 '21 at 13:15
  • **READ THE ERROR MESSAGE** Its says `Unknown column >>> 'name' <<< in 'where clause' ` – RiggsFolly Jun 30 '21 at 13:20
  • Alright I fixed it ! It was indeed a typo ! Thanks a lot for your help RiggsFolly ! – Benjamin A Jun 30 '21 at 13:22