Jump to content

$input->post vs. JS fetch


Recommended Posts

Hi guys.

On my frontend I'm using fetch to submit stuff. Is there a neater way to access this from PHP other than the vanilla json_decode(file_get_contents('php://input')) ?

$input doesn't seem to get anything from such a request.

Link to comment
Share on other sites

I am assuming you are using fetch() to send an Ajax request to some endpoint. ProcessWire will not recognise Ajax requests without the below in the header:

'X-Requested-With': 'XMLHttpRequest'

The this will work:

<?php

if($config->ajax){
// handle ajax request here
  $id = (int) $input->some_input_with_id;
}

 

Link to comment
Share on other sites

To make a POST request using the Fetch API, you need to pass the 'method: POST' to the fetch() method as the second parameter: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch | https://reqbin.com/code/javascript/ricgaie0/javascript-fetch-api-example

fetch('https://domain.com/api', {
  method: 'POST' 
}) 
  .then(resp => resp.json()) 
  .then(json => console.log(json))

 

  • Like 1
Link to comment
Share on other sites

@kongondo thanks, that certainly makes the detection more elegant. Still have to json-parse the "php://input" to get to the object that I'm passing, though. Example:

$fetchVars = json_decode(file_get_contents('php://input'), true);
include('./form-processors/'.$fetchVars['form-name'].'.php');

Wouldn't it make sense to have something more processwirey for this as well?

Link to comment
Share on other sites

Well, you can just send your POST request in such a way that the Json will be available as $input->post['myData'], that is, as FormData or UrlEncoded:

fetch('https://example.com', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Requested-With': 'XMLHttpRequest' },    
    body: new URLSearchParams({ 'myData': JSON.stringify(someObject) })
});

or

const formData = new FormData();
formData.append('myData', JSON.stringify(someObject));
fetch('https://example.com', {
    method: 'POST',
    headers: { 'X-Requested-With': 'XMLHttpRequest' },
    body: formData
});

If your object is just a simple key-value affair, you may actually want to send it that way and not as Json at all, because you’ll be able to use the sanitizer methods for each value. With the Json you have to parse it and then sanitize the properties, watch out for properties you didn’t want etc.

  • Like 2
Link to comment
Share on other sites

Hey @Jan Romero thx for that post 🙂 I've never really understood how such things work and when to use what syntax. When to send a body, when json etc.; Some 3rd party API docs use php://input others use $_GET... Do you have some pointers to make me understand better what's going on and where to use what? Up until now I've managed to get everything working, but sometimes it was just try and error. For example how did you know to use application/x-www... and why are you using URLSearchParams as body?

Thank you!

Link to comment
Share on other sites

@bernhard Admittedly, I had never really paid attention to php://input, so this thread prompted me to google it. As I understand it, that stream always contains the raw request body, so anything could be in there, however only two content-types end up in $_POST and thus also in PW’s $input->post: application/x-www-form-urlencoded and multipart/form-data. For these, in addition to sorting everything into an associative array, PHP also takes care of unescaping the URL encoding.

When OP wants to send Json, I’m assuming he quite sensibly declares application/json. PHP doesn’t know this content-type (plus, the whole thing is a nameless Json object, so what would be the key for $_POST’s associative array?), so nothing happens automagically. This answer on SO gives a lengthy overview on how to handle php://input.

If you’re asking about the client-side fetch() API, I have to confess I didn’t test the code I posted, but the idea is to create a request with the content-types application/x-www-form-urlencoded or multipart/form-data mentioned above. Indeed, for some reason I thought it would be necessary to specify the former content-type, but it’s actually set automatically when URLSearchParams are used for the request body (at least in Firefox). Likewise, when the body is of type FormData, the default content-type will be multipart/form-data.

As for when to send a body, it’s just the HTTP request’s content, so I guess whenever you want to transmit data to the server, i.e. usually with POST (or PUT or something). When dealing with third party APIs you gotta do the weird things they want you to, of course. If it’s your own PHP/ProcessWire site you send requests to, I’d say it doesn’t really matter whether it’s application/x-www-form-urlencoded or multipart/form-data (or URLSearchParams or FormData for that matter), since both deliver keys and values that end up in $_POST/$input->post. In this case I would just use whatever is more convenient to assemble in JS, i. e. if the data actually comes from a HTML form, you can pass the form element to FormData’s constructor and you’re done.

Sorry if I’m not telling you anything new here 😅 Trial and error makes up a large chunk of my modus operandi as well m)

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...