0

The Issue

I have a problem where I have seen similar questions in an albeit different context regards to $_POST and $_GET requests with PHP. A typical example being PHP mixing POST and GET Requests to one page

In my instance the GET is being taken from query string in a URL, and out of the box the functionality all works as expected when deleting an image component (a container that holds an image) from a page.

The problem I have is I am using using the JavaScript fetch() API for this deletion so that the page doesn't do a hard refresh. When this process happens with JavaScript fetch() the image component is removed from the page but when you refresh the page the image component reappears.

I am using almost identical code on a different page, and when this problem occurred, moving the GET request below the POST request solved the problem. Alas, this isn't happening this time (and on that other page there is only one potential POST request form).

All of the forms that use $_POST are processed on the same page that the forms themselves appear on (i.e. no action attribute is used). Only one POST request happens at any one time.

Question

My question is thus, how do I approach / solve this without using the dreaded $_REQUEST. I noticed one of the answers to the general problem of GET and POST suggested using if($_SERVER['REQUEST_METHOD'] == 'POST') { ... } but this isn't an option (I don't think) because there are three potential $_POST forms on the page that all have different functionality and name attributes.

Below are the GET and POST code blocks in the order in which they appear.

Note: I only included the PHP PDO for the 'remove image from board' code block because this is the only aspect with JavaScript fetch() and I know this works OK with no JavaScript. There is also potentially a lot of code I could share which I'm happy to do, but thought I'd post a slimmed down version of the code first in case there is an obvious answer that I'm completely missing. There is only one $_POST request executed at any one time.

There are header() functions in each POST block, although I don't see that being the source of the problem?

Also, this is all quite new to me.

JavaScript

// the form iteself
const fetchForms = document.querySelectorAll('.js-fetch-form'),

// <figure> element that is deleted
removeableImageComponent = document.querySelectorAll('.removeable-image-component');

// URL details
let myURL = new URL(window.location.href),
pagePath = myURL.pathname

fetchForms.forEach((item) => {
    item.addEventListener('submit', function (e) {
        if (e.submitter && e.submitter.classList.contains('js-delete-button')) {
            e.preventDefault();

            var formData = new FormData(this);

            formData.set(e.submitter.name, e.submitter.value);

            fetch(
                pagePath, {
                method: 'post',
                body: formData
            })
            .then(function(response) {

                if (response.status === 200) {
                    if (e.submitter && e.submitter.classList.contains('js-delete-button')) {
                        e.submitter.closest('.removeable-image-component').remove();
                    }
                }

                return response.text();

            }).catch(function(error) {
                console.error(error);
            })

        }
    })
})

HTML

<figure class="removable-image-component">
    <form class="js-fetch-form" method="post">
        <input type="hidden" name="user-id" value="03">
        <img src="path/to/image.jpg">
        <button class="js-delete-button" name="image-delete" value="52">Remove from board</button>
    </form>
</figure>

PHP

// value from URL
if (isset($_GET['board-id']) ) {
    $boardId = $_GET['board-id'];
} else {
    header("Location: login.php");
    exit;
}

// UPDATE BOARD NAME
if(isset($_POST['submit-new-board-name'])) {

    // PDO updates to database

    header("Location: {$wwwRoot}/board.php?board-id={$boardId}"); exit;
    
    }
}

// ================
// DELETE THE BOARD
// ================

if (isset($_POST['delete-board'])) {

    // PDO updates to database

    header("Location: {$wwwRoot}/boards?id={$sessionId}"); exit;
}

// =======================
// REMOVE IMAGE FROM BOARD
// =======================

if(isset($_POST['image-delete'])) {

    $imageId = $_POST['image-id'];

    $stmt = $connection->prepare("DELETE FROM boards_images WHERE board_id = :board_id AND image_id = :image_id");
    $stmt->execute([
    ':board_id'=>$dbBoardId,
    ':image_id'=>$imageId
    ]);

    header("Location: {$wwwRoot}/board?board-id={$dbBoardId}"); exit;
}
paulo77
  • 174
  • 14
  • If you're using `fetch()` then the forms in the HTML are irrelevant. All the parameters come from the `fetch()` body, and you'll need to send the parameters that the PHP code checks to tell which case it is. – Barmar Sep 22 '22 at 20:09
  • Please show your client-side code, that's where the problem is. – Barmar Sep 22 '22 at 20:11
  • @Barmar I've added the client side code and also the PDO code for the PHP code block in question - although as mentioned in the question I know this works having tested it without the javascript fetch() – paulo77 Sep 22 '22 at 20:31
  • You should use `myURL` as the URL to submit to, not `pagePath`, so that it includes the `board-id=` query parameter. – Barmar Sep 22 '22 at 20:37

1 Answers1

1

Change

            fetch(
                pagePath, {
                method: 'post',
                body: formData
            })

to

            fetch(
                myURL, {
                method: 'post',
                body: formData
            })

pagePath is the URL without the scheme or query parameters, so ?board-id=### is missing. To emulate how the normal form submission works when you leave out the action URL, you should submit to the entire URL.

Barmar
  • 741,623
  • 53
  • 500
  • 612