-2

I am trying to delete database entry with DELETE http request sent from axios in REACT.

    function Delete() {
        const form = new FormData();
        for (var i = 0; i < selected.length; i++) {
            form.append(i, selected[i]);
          }
        console.log(form)
        axios.delete(url, form)
        navigate(`/`)
    }

As you can see here, I iterate over "selected" which is an array and assign keys in the form as numbers. For example first key in form is 1 with first "selected" value and so on. Then comes the PHP code.

header('Access-Control-Allow-Origin: http://localhost:3000');
header("Access-Control-Allow-Methods: GET, POST, DELETE");
$servername = "localhost";
$username = "root";
$password = "";
$conn = new mysqli($servername, $username, $password, 'commerce');
$method = $_SERVER['REQUEST_METHOD'];
switch ($method) {
  case "DELETE":
    parse_str(file_get_contents("php://input"), $_DELETE);
    for ($i = 0; $_DELETE; $i++) {
      $sku = $_DELETE[$i];
      $delete = $conn->prepare("DELETE FROM baseinfos WHERE sku='$sku'");
      $delete->execute();
    }
    break;

Here I am supposed to get the values of DELETE form, iterate over key values (which are numbers and iteration should work) and delete the corresponding entries in the database. Nothing happens, not even an error is thrown. What should I do?

Dharman
  • 30,962
  • 25
  • 85
  • 135
Leon_idas
  • 141
  • 12
  • Any question that mentions both client side technology and SQL is automatically off topic. You are supposed to debug the client-server interaction and make your mind whether your problem is related to sending any data to server OR using that data on the server. Instead of running any SQL queries you must confirm first, whether the data is correct. – Your Common Sense Jun 30 '23 at 04:19
  • 1
    Also, [your prepared statement is a cargo cult code](https://phpdelusions.net/pdo/cargo_cult_prepared_statement) – Your Common Sense Jun 30 '23 at 04:31

2 Answers2

0

Bodies on DELETE requests are not a good idea and generally should be avoided. The purpose of a DELETE request is to delete the resource identified by the URL you are using.

In your case, it looks like you want to define a generic operation that deletes a number of different items. POST is more appropriate for this.

Servers and clients may drop DELETE request bodies because DELETE request bodies are not intended to be meaningful.

From the latest HTTP specification:

Although request message framing is independent of the method used, content received in a DELETE request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). A client SHOULD NOT generate content in a DELETE request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

https://www.rfc-editor.org/rfc/rfc9110.html#name-delete

Evert
  • 93,428
  • 18
  • 118
  • 189
  • _"an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported"_... given OP controls the server, I'd say this caveat applies – Phil Jun 30 '23 at 00:48
  • Continue reading after that sentence. Aside from the technical implication, it's also a bad use of `DELETE` and it's semantic intent. Doing the correct thing is obviously more a better choice with no real drawbacks other than potentially cosmetically. – Evert Jun 30 '23 at 01:03
  • I've seen [far too many arguments around GET request bodies](https://stackoverflow.com/q/978061/283366) (thanks ElasticSearch for that nonsense) to care much about it any more. If OP wants to send a DELETE request body for their own, non-public API then more power to them. At least browsers let you do that (as opposed to GET where its forbidden) – Phil Jun 30 '23 at 01:54
  • @Philisonstrike then perhaps for intellectual honesty you can at least acknowledge that it's at least contentious, and that in itself is not always great. BTW the question you linked to is mine from many years ago. I wrote a longer follow-up last year that you might like and has a healthy amount of nuance I hope: https://evertpot.com/get-request-bodies/ – Evert Jun 30 '23 at 02:49
  • 1
    Oh, I absolutely acknowledge it. In my opinion, GET and DELETE requests should be idempotent and have no request body. I guess I was more focusing on the actual problems in the question above rather than ideological approaches to REST. By no means am I discounting your answer and I hope OP takes it to heart. Thanks for the link to your article – Phil Jun 30 '23 at 03:44
  • @Philisonstrike thank you phil! And agreed that it _is_ a bit of a tangent. – Evert Jun 30 '23 at 04:31
-1

The first problem is that the signature for axios.delete() is

axios.delete(url[, config])

If you want to send a request body, you need to do so in the config object's data property.

Secondly, sending FormData in the request body uses content-type: multipart/form-data which is not the format parse_str() works with.

Parses string as if it were the query string passed via a URL

I would highly recommend using JSON for this instead. Simply send the selected array directly

axios.delete(url, { data: selected });

Axios will encode this as JSON and set the appropriate content-type: application/json header automatically.

To read this on the PHP side, use the following

$skusToDelete = json_decode(file_get_contents('php://input'));
$stmt = $conn->prepare('DELETE FROM baseinfos WHERE sku = ?');
$stmt->bind_param('s', $sku);
foreach ($skusToDelete as $sku) {
    $stmt->execute();
}

Note that I've used bound SQL query parameters which are a lot safer. You also only need prepare a query statement and bind parameters once. It can then be executed in a loop.

Phil
  • 157,677
  • 23
  • 242
  • 245
  • Hey, thanks for answering! Regarding the json, should I create an empty array and add json objects to it in the React part? I created the array with objects and sent it to PHP but $skusToDelete is null... – Leon_idas Jun 29 '23 at 07:06
  • foreach() argument must be of type array|object, null given – Leon_idas Jun 29 '23 at 07:11
  • you might also try `JsonString = JSON.stringify(selected);` and pass that on the axios call – RiggsFolly Jun 29 '23 at 09:53
  • @RiggsFolly Axios takes care of that automatically – Phil Jun 29 '23 at 19:53
  • @Leon_idas my bad, I forgot the parameters for `axios.delete()`. Have fixed it now – Phil Jun 29 '23 at 19:55