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 am going CRAZY posting a json request to a php webservice file when the object I am trying to send is multi-level. ie:
postdata = {
name:"francesco"
, age:58
, address : {
street:"my Street"
, number: 42
, city:"London"
}
}
I have tried every example on the web, but, when I read the $_POST data on the php webservice two things happen:
if I use JSON.stringify I dont get anything on $_POST or $_GET depending what method I use, and I have to read the file_get_contents('php://input') and then json_decode it (whereas calling the webservce from php I get the info tidily in my $_GET or $_POST globals),
If I use other methods I have found, I get the name and age fine, but the address comes through as "[object object]" .
My question is, is it possible, WITHOUT USING jquery, to :
- create an object in javascript (multilevel or however the right term)
- use the "XMLHttpRequest()" object to post it to the php ws?
- read it from php using the $_GET or $_POST globals (depending on method used)?
I have been going crazy for over 96 hours now!!!
Thanks!
Francesco
So many incorrect answers here.
To POST a nested object to your PHP script you can use plain js:
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://yourwebsite.com/yourscript.php");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send({"data":postData});
To read the info server-side
$postData = $_POST['data'];
When I looked to see what PHP had actually given me with error_log(print_r($_POST['test'], true)) I got
Array
(
[name] => francesco
[age] => 58
[address] => Array
(
[street] => my Street
[number] => 42
[city] => London
)
)
It's all there.
Question #1
is it possible to create an object in javascript (multilevel or however the right term)
This is how you create an object in javascript:
var o = {
foo: "bar"
};
Question #2
is it possible to use the "XMLHttpRequest()" object to post it to the php ws?
It's not hard to find it on the web: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
The code would be something like:
var oReq = new XMLHttpRequest();
oReq.open("POST", "http://www.example.org/target");
oReq.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
oReq.send(JSON.stringify(postdata));
Question #3
is it possible to read it from php using the $_GET or $_POST globals (depending on method used)?
No, you can't. As the docs say, $_POST is:
An associative array of variables passed to the current script via the HTTP POST method when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request.
So the $_POST is usable only if you're passing form encoded data. Since you're passing a JSON, you're supposed to parse the request body by yourself.
From what I understand, it is not possible to post data to php from jscipt unless it's a form. but I can do this:
if ($_POST != null)
$req = $_POST;
else {
$json = file_get_contents('php://input');
$req = json_decode($json, true);
}
.. and then just read the $req ..
Is this VERY dirty or commonplace??
I've been doing something this at the bottom of all my views:
<script type='text/javascript'>
$.post('php/ajax.php', {type:'session'}).done(function(data){
var session = JSON.parse(data);
$(document).ready(function(){
$.getScript('resources/redactor/redactor.js');
$.getScript('javascript/year_long_calendar.js');
$.getScript('javascript/edit_lesson_modal.js');
});
});
</script>
This works really well for me. All my scripts get loaded inside of a single docReady, and all my ajax requires a token that gets generated upon login and stored in $_SESSION. This stops people from hitting my ajax logic using fake headers. By doing this, my ajax calls look something like:
$.post(url:'ajax.php', {token:session.token, id:id}).done(function(data){ ... });
I can also access other session variables
var user_id = session.user_id;
Since I've been doing this from the start of the project, I intentionally keep any sensitive information like passwords out of the session variable. What are your thoughts on this? Does any of this strike you as insecure, or terribly inefficient? I realize $.getScript is often used as a lazy way to load libraries, but I think I've found a pretty valid use for it.
None of the data in $_SESSION is sensitive except the token, and you have to be logged in to get one. Unless someone malicious hops on a machine while the real user is away and knows exactly where my ajax logic is, how it works, how I store my session, and fakes a quick header on PostMan to delete all my tables, I don't see it being an issue.
EDIT:
#AnotherGuy helped me realize a much better solution. My ajax.php file now looks like this:
<?php session_start();
include('connect.php');
include('functions.php');
// check to see if http request is ajax (easy to fake but hey might as well)
if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'){
// when the user logs in, a random number is generated and saved to $_SESSION['token'].
// this block is used to pass the token to a javascript variable securely
if($_POST['type'] == 'session'){
$session = [
'token'=>$_SESSION['token'],
'user_id'=>$_SESSION['user_id']
];
echo json_encode($session);
}
// all post requests must pass the correct token variable to step into this block and access the ajax logic
if(isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
if($_POST['type'] == 'get'){
$where = null;
if(isset($_POST['where'])){
$where = json_decode($_POST['where']);
}
$order_by = null;
if(isset($_POST['order_by'])){
$order_by = json_decode($_POST['order_by']);
}
echo json_encode(get($_POST['db'], $_POST['table'], $where, $order_by)->fetchAll());
}
if($_POST['type'] == 'put'){
$set = json_decode($_POST['set']);
echo put($_POST['db'], $_POST['table'], $set);
}
if($_POST['type'] == 'update'){
$set = json_decode($_POST['set']);
$where = json_decode($_POST['where']);
update($_POST['db'], $_POST['table'], $set, $where);
}
if($_POST['type'] == 'delete'){
$where = json_decode($_POST['where']);
delete($_POST['db'], $_POST['from'], $where);
}
From how you describe you are using the session I cannot see any harm in it, but I still think it is dangerous. Imagine you in the future work on another project and then come back to this. Will you still remember not to store any sensitive information inside the session? As a basic rule of thumb is to never store sensitive information in the session unless it is the only solution, which it rarely is. But sometimes mistakes are made and they can hurt you!
I would change this to something that looks/works in the same way, but offers you more decoupling from the session. If you are fetching the entire session you are bound to retrieve some information which would never be used or should never be available to client side (through Javascript). I would create a single page that you request which can only provide the necessary information. That way you can also ensure only required information is exposed to the client side.
So instead of requesting a generic ajax.php file, I would create a page called (or something like it) userInfo.php. That way you can also eliminate the type variable you send along with it.
Hope this can help you, happy coding!
You could store that session data in browser with sesssionStorage in a serialized JSON string and manipulate it from there. Many recommend this approach over using cookies W3Schools
Cheers.
I realize that calling database from JavaScript file is not a good way. So I have two files:
client.js
server.php
server.php has multiple functions.
Depending upon a condition, I want to call different functions of server.php.
I know how to call server.php, but how do I call different functions in that file?
My current code looks like this:
function getphp () {
//document.write("test");
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
// data is received. Do whatever.
}
}
xmlhttp.open("GET","server.php?",true);
xmlhttp.send();
};
What I want to do is something like (just pseudo-code. I need actual syntax):
xmlhttp.open("GET","server.php?functionA?params",true);
Well based on that premise you could devise something like this:
On a sample request like this:
xmlhttp.open("GET","server.php?action=save",true);
Then in PHP:
if(isset($_GET['action'])) {
$action = $_GET['action'];
switch($action) {
case 'save':
saveSomething();
break;
case 'get':
getSomething();
break;
default:
// i do not know what that request is, throw an exception, can also be
break;
}
}
Just do something like this, i hope this will work
xmlhttp.open("GET","server.php?function=functioName¶msA=val1¶m2=val2",true);
You will most likely need to create the mechanism yourself.
Say the URL will look like server.php?function=foo¶m=value1¶m=value2
On the server side you will now have to check whether a function with such a name exists, and if it does, call it with these parameters. Useful links on how to do it are http://php.net/manual/en/function.function-exists.php and http://php.net/manual/en/functions.variable-functions.php
Otherwise, if you don't want to have it like this, you can always go with if/switch and simply check that if $_GET["function"] is something, then call something etc.
You can use jQuery too. Much less code than pure js. I know pure js is faster but jQuery is simpler. In jQuery you can use the $.ajax() to send your request. It takes a json structured array like this:
$.ajax({
url: "example.php",
type: "POST",
data: some_var,
success: do_stuff_if_no_error_occurs(),
error: do_stuff_when_error_occurs()
});
Here's a dynamic way to solve this issue:
xmlhttp.open("GET","server.php?action=save",true);
PHP Code:
<?php
$action = isset($_GET['action']) ? $_GET['action'] : '';
if(!empty($action)){
// Check if it's a function
if(function_exists($action)){
// Get all the other $_GET parameters
$params = array();
if(isset($_GET) && sizeof($_GET) > 1){
foreach($_GET as $key => $value){
if($key != 'action'){
$params[] = $value;
}
}
}
call_user_func($action, $params);
}
}
?>
Keep in mind that you should send the parameters in the same order of function arguments.
Let's say:
xmlhttp.open("GET","server.php?action=save&username=test&password=mypass&product_id=12",true);
<?php
function save($username, $password, $product_id){
...
}
?>
You can't write the API Call that way:
xmlhttp.open("GET","server.php?action=save&password=mypass&username=test&product_id=12",true);
Keep in mind that it's really bad to send "function namespaces" along with the parameters to a back-end. You're exposing your back-end and without proper security measures, your website will be vulnerable against SQL Injection, dictionary attack, brute force attack (because you're not checking a hash or something), and it'll be accessible by almost anyone (you're using GET using of POST and anyone can do a dictionary attack to try to access several functions ... there's no privileges check) etc.
My recommendation is that you should use a stable PHP Framework like Yii Framework, or anything else.
Also avoid using GET when you're sending data to the back-end. Use POST instead.
I am having trouble with setting cookies in laravel via ajax. I have read a number of questions/posts to no avail.
I have a drop down, that when changed, uses js to post its value to a controller which sets the cookie and returns a response with that cookie, then the page is refreshed upon ajax completion, and in the document.ready script, it calls a get cookie route, which retrieves the value from that cookie. it appears the cookie isn't being sent? I know the get path works, as if I set the cookie elsewhere it retrieves it properly. I have also used headers_sent() to ensure that headers haven't already been sent prior to setting the cookie and returning the response. I have also tried a number of different approaches that I have seen in other SO questions and answers, including Cookie::queue, $response->withCookie($cookie) and $response->headers->setCookie($cookie), none of which I've found to work.
Is there a problem with my approach? or is it more likely a syntax problem?
My javascript:
function trans(lang){
$.post( 'cookie/set' , {'name':'language', 'value':lang, 'timeout':-1})
.done(function(data){
removeEvent();
}).always(function(){
window.location.reload();
});
}
Controller function for cookie/set:
public function postSet(){
$name = Input::get('name');
$value = Input::get('value');
$timeout = Input::get('timeout');
if(Request::ajax()){
Log::info('cookie', array('name'=>$name, 'value'=>$value, 'timeout'=>$timeout));
$cookie = Cookie::make($name, $value, $timeout);
$response = Response::make();
$response->headers->setCookie($cookie);
return $response->withCookie($cookie);
}
}
doc.ready javascript:
$(document).ready(function(){
$.post( 'cookie/get' , {'name':'language'})
.done(function(data){
if (!data){
alert('no cookie');
}
$("#language").val(data);
removeEvent();
});
})
and finally the cookie/get controller function:
public function postGet(){
$name = Input::get('name');
define('__TRANSLATEMODE',"raw");
return Cookie::get($name);
}
Again, I can confirm the get route works correctly. My thought is that somehow the cookie isn't being returned with the response from the set ajax call, but I don't understand why.
Thanks in advance for your help!
-Wally
EDIT:
I looked at the request and responses in firebug, and it appears that the response from the postSet route does not contain the cookie. I had somewhat suspected this. but at least this nails down the source of the problem. Still not sure why it doesn't want to work though.
Edit 2:
I solved it. Not fully sure why this works, but the code below now works. It seems that returning an empty response would not send cookies with it? I dunno, it's solved at least. I will answer this when it will let me, and mark it as accepted. (If anyone knows WHY this fixed it, comments would be greatly appreciated.)
public function postSet(){
$name = Input::get('name');
$value = Input::get('value');
$timeout = Input::get('timeout');
Cookie::queue($name, $value, $timeout);
$response = Response::make();
return Response::make('test');
}
Thanks to those who looked, and hopefully this helps someone else.
-Wally
I can see you have a js Post function with a Get Route. This will not work in Laravel.
Not sure if this the entire issue but checking the routes will defintely help you narrow it down.
I solved it. Not fully sure why this works, but the code below now works. It seems that returning an empty response would not send cookies with it? I dunno, it's solved at least. I will answer this when it will let me, and mark it as accepted. (If anyone knows WHY this fixed it, comments would be greatly appreciated.)
public function postSet(){
$name = Input::get('name');
$value = Input::get('value');
$timeout = Input::get('timeout');
Cookie::queue($name, $value, $timeout);
$response = Response::make();
return Response::make('test');
}
Thanks to those who looked, and hopefully this helps someone else. -Wally
I'm writing a script to retrieve the scores from an osu! beatmap. The script uses the osu! API, which can be found here. I've obtained a valid API key, and got the info from the website. My project can be found here: failosu!.
This script is called by AJAX, and the variable s is passed via POST.
My problem is with the returned array.
In the following snippet (not really, it's pretty much my entire script), I make a request for the beatmap information first. In doing this, I am passing a variable, s (beatmap set ID), to the server, and trying to get the variable b (beatmap ID).
However, whenever I call $d1['beatmap_id'], it doesn't return anything to the main page. Instead, my AJAX script runs the error function rather than the success function. Does anyone know what my problem is?
if($_POST['id']) {
$s = $_POST['id'];
$k = "xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$u0 = "https://osu.ppy.sh/api/get_beatmaps?k=".$k."&s=".$s;
$d0 = json_decode(file_get_contents($u0));
$d1 = get_object_vars($d0[0]);
$b = $d1["beatmap_id"];
// THE CODE STOPS WORKING HERE FOR SOME REASON ????
$u = "https://osu.ppy.sh/api/get_scores?k=".$k."&b=".$b."&m=0";
echo $u;
$d = json_decode(file_get_contents($u));
for($i=0;$i<count($d);$i++) {
echo "<li>".$i." ".$d[$i]['username']."</li>";
}
}
Does anyone know what's wrong? Do you need me to tell you more information about my code?