I need to make a PATCH request to a PHP application.
How can I get the data from that PATCH request inside that application?
If I had to do it with a POST, it would just be a simple access to the global $_POST variable.
I know that this has been solved, but for anyone who was hoping for an answer like
$_PATCH["name"];
there is a way to do that:
parse_str(file_get_contents('php://input'), $_PATCH);
then you can access it like $_GET["something"] and $_POST["something"] just do
$_PATCH["something"]
hope that helped someone :)
You can get data with php://input stream wrapper:
$data = file_get_contents('php://input');
Also make sure your web server supports PATCH requests, some are configured to respond only to GET and POST.
Since none of the above has worked for me in PHP 5.6, here's a solution that actually did.
I used this parse_raw_http_request($data) function by Christof.
And here's the code:
$_PATCH = [];
parse_str(file_get_contents('php://input'), $_PATCH);
parse_raw_http_request($_PATCH);
// From now on, the $_PATCH variable keeps all request arguments as well,
// and they're accessible under approprate keys like $_PATCH['yourKey']
i'm using : PHP 7.4
function patchMethod(){
parse_str(file_get_contents('php://input'), $_PATCH);
$body=[];
if (is_array($_PATCH)) {
foreach ($_PATCH as $key => $value) {
$body[$key] = $value;
}
}
return $body;
}
You have $_REQUEST superglobal containing all data we can get regardless the HTTP method used (GET, POST, PATCH, PUT)
Related
I'm trying to write a REST API in PHP from the ground up for my website, partly as a learning exercise, partly to develop a codebase that I can reference later in case I forget how something works.
To my dismay, I've discovered that PHP has no $_PUT superglobal.
Remembering that Laravel makes GET/PUT/POST/DELETE distinctions, I figured Laravel must have code to handle HTTP PUT requests correcly, but no, in fact, it depends on a hidden form field with the value "_PUT" to specify the action to take.
Without the need to process files, is there any way to take multipart/form-data and parse it into an associative array in a similar fashion to $_POST, such that it is foreach iterable?
Here is what I tried and it simply doesn't work. I'm not understanding what the extra data is that is sent, must be related to the PHP session?
parse_str(file_get_contents("php://input"), $_PUT);
foreach ($_PUT as $key => $value)
{
unset($_PUT[$key]);
$_PUT[str_replace('amp;', '', $key)] = $value;
}
$_REQUEST = array_merge($_REQUEST, $_PUT);
foreach($_PUT as $key=>$value){
$ani->state[$key]['value'] = $value;
}
What I end up getting out of this looks like this: (I am pretty sure I can beat this into what I want, but I don't think what I come up with is going to be robust enough to trust not to break all the time.)
So as not to anger anyone, the code I'm using came directly from here: https://joshtronic.com/2014/06/01/how-to-process-put-requests-with-php/
I tried to spin my own, which ended up looking very similar to his, minus merging the body back into the request, which I still don't completely understand the purpose of.
My solution is now simply to not use multipart/form-data and instead use application/x-www-form-urlencoded. I don't know if this decision will haunt me later on down the road but it solves my problem for now. I can still use this for my API as in JavaScript I can specify the content type as such:
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
I'd be very interested in knowing why PHP doesn't add a $_PUT superglobal?
I have a central PHP script I use for handling many requests from my page, using XMLHttpRequest() calls from JavaScript, using the GET method. My server PHP is currently 5.6, and yes, I'm avoiding synchronous calls.
It all works well, however there are cases where I'd prefer NOT to have the request remain in browser history, or even be displayed in the URL. So based on the MDN reference on this call, I thought I could simply switch to the POST method, keeping my existing requests (such as "http://myscript.php?cmd=dothis&data=somedata"). then all I'd have to do is add some code to my PHP script, so I could gather the passed data either way...
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if(isset($_GET['cmd'])) $cmd = $_GET['cmd'];
if(isset($_GET['data'])) $data = $_GET['data'];
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if(isset($_POST['cmd'])) $cmd = $_POST['cmd'];
if(isset($_POST['data'])) $data = $_POST['data'];
}
Well obviously i was dead wrong. What I found was...
Neither of the variables shown in this example are seen by the script within the $_POST array, when I switch to the POST method.
Switching from the $_POST array to the $_REQUEST array works fine (eg: "if(isset($_REQUEST['cmd'])) $cmd = $_REQUEST['cmd']);" ), BUT....
Just the act of issuing my XMLHttpRequest() calls with the POST method, results in errors like this in my log:
PHP Deprecated: Automatically populating $HTTP_RAW_POST_DATA is
deprecated and will be removed in a future version. To avoid this
warning set 'always_populate_raw_post_data' to '-1' in php.ini and use
the php://input stream instead. in Unknown on line 0
So obviously This is a dead end. Doing my best to research what is going on here, in the PHP manual reference to POST I read this right on top...
$_POST $HTTP_POST_VARS [deprecated]
So if I'm understanding this right, the reason I can only obtain the POST variables using the $_REQUEST array is because my requests are still formatted as if I were still using GET, which (apparently?) is a deprecated method. Therefore, "coaxing" it to work is just moving the problem to the future.
Incidentally, I can see by calling the phpinfo.php on my server that despite the ERROR I see in my logs, "always_populate_raw_post_data" is indeed already set to "-1". So all the "solutions" I've found recommending I "JUST" make this setting in my PHP.INI file do not help.
And even if it DID "hide" the error, doing so seems irrelevant to me. Am I wrong in saying that even if I simply gather my passed PHP vars from the $_REQUEST array when using the POST method, AND figure out a way to suppressing the "deprecated" warnings in my LOG, the whole scheme would still fall apart (and make my POST requests fail), the day I finally migrate to PHP 7.x.?
I apologize for asking here, but I have really tried to search every reference I could find for both doing XMLHttpRequests using POST method, AND the deprecated error messages I get in my logs. There is so much obsolete info out there, I can't find any clear discussion on how to PROPERLY alter or re-format my XMLHttpRequests so that I can use the POST method. In fact, I can't even positively determine whether doing so will be possible beyond PHP.5.6. Any help will be very much appreciated.
PHP made a mistake of naming $_GET and $_POST after the default place that a web browser will put data in an HTML form where the method attribute is set to GET or POST.
$_GET gets data from the query string, even if the request method was POST.
The request body is determined by the argument you pass to send. Data you put in the query string remains in the query string.
const url = 'http://myscript.php'
const form_data = new FormData();
form_data.append("cmd", "dothis");
form_data.append("data", "somedata");
cost xhr = new XMLHttpRequest;
xhr.open("POST", url);
xhr.addEventListener('load', function () { console.log(this.response); });
xhr.send(form_data);
For one of my Laravel Web app I want to log all the Request Parameters(Post as well as Get) in database in Json Format for that I am using $request->all() Method, which results in an exception when user tries to upload any file.
that's why I want a way to select only Serializable Parameters from the request.(for get as well as for post Requests) or a way to select all the request parameters except files.
Request::except([]) will not work for me since in Except method we will have to provide the file parameter names.
In my project, i used this except for many fields like below,
$input = $request->except('first_name', 'middle_name', 'last_name', 'address',...);
It is work fine for me.
I stored all the remain values into $input and store values from that input variable.
Please try this one.
In your case please take this debug code for test once, might be you like it to use in your current work
$allRequestParams = array_map(function($input) {
return !is_array($input) ? $input : false;
}, $request->all());
echo '<pre>';
print_r($allRequestParams);
echo '<pre/>';
die;
Since any of the answer didn't work for me I did lots of reading and some digging about laravel but still I could not find the specific solutions I was looking for, so I did a small hack, instead of using Laravel's Request Object and pulling parameters from there I simply used PHP's built in $_REQUEST parameter.
Eg.
$non_file_parameters = $_REQUEST;
$_REQUEST will have both Get as well as Post Parameters except file Parameters coz in Core PHP for files we have $_FILES super global variable.
Thanks guys for your efforts...
framework is here
http://luracast.com/products/restler/
i'm using restler as restful api for my work,
when i use backbone model save to a url, it sends and update my data as json by using 'HTTP PUT' request method, and i want to get a response from what i've putted...
if it's a HTTP POST request method i can use
// to getting content from a POST
$post_data = json_decode(file_get_contents('php://input'), true);
to get my content, but cant get anything from HTTP PUT
// can't get anything from a PUT
function putpatients($id) {
$post_data = file_get_contents('php://input');
$post_data = json_decode($post_data, true);
echo $post_data['name'];
}
the browser response blank
how do i return my data as json ???
As I commented on your question, php://input is a stream, if you read from it, it empties it.
I've never used Restler before but looking at the few examples provided in their download, it seems to indicate the submitted data is automatically passed as a parameter to your put handler..
In Restler's crud example, the Author class has a put request like this:
function put($id=NULL, $request_data=NULL) {
return $this->dp->update($id, $this->_validate($request_data));
}
so i'm guessing that restler has already read the php://input stream, and hence emptied it.
so, your put handler should maybe be more like in their example:
function putpatients($id, $request_data = NULL) {
/* do something with the $request_data */
var_dump($request_data);
}
Edit: There's actually a previous SO question from #deceze that talks about why reading twice from php://input doesn't work - for PUT requests - which explains why your code worked with a POST request. Either way, you should really use the facility provided by Restler rather than re-inventing the rest wheel.
Does the developer tool of your choice (firebug etc.) show a response?
If so it could help if you put echo json_encode($post_data['name']); instead of your echo.
try to use print_r() function for displaying the values of the variable example:
print_r($post_data);
I managed to make a bunch of webservices with symfony using GET parameters, but i need to use POST parameters for a signup webservice.
But when I try to get those POST parameters, for example $request->getParameter('test');, they just return a null value.
How comes ?
EDIT
Here's a straightforward exemple
testSuccess.json.php
{
"test": <?php echo json_encode($test); ?>
}
action.class.php
public function executeTest(sfWebRequest $request) {
$this->test = $request->getParameter('test');
}
That would indicate that there isn't a POST parameter called 'email' sent with your request. Apart from that there's not much anyone else can say about your problem without additional information.
I have run into the same problem. It seems that when one does not use
Content-Type: application/x-www-form-urlencoded
these parameters are not available in Symfony. I cannot find anything in the http documentation that dictates this content type for these methods. I have created a symfony_ticket for this bug.
So, to fix your issue add this Content-Type header to your request.
There is a way around the issue with the POST parameters being lost with JSON object posts. Instead of using the various parameter methods you need to use the:
$request->getContent()
Which shows the JSON as a string within the body of the post. Having the content set as application/json, Symfony effectively ignores the content so doesn't pickup the parameters in the body.