Can't send a Multidimensional Array from JavaScript trough AJAX to PHP - javascript

I saw a lot of problems regarding the exact same thing. But I tried so many thing's that I'm really not sure if what I'm doing even works anymore.
So, I have this multi-dim array, wich I create by looping trough an html table., I want to send it to PHP, so I can loop it, and create the objects I need to store it in a database.
But all I get from PHP when I try to loop it trough a for each is "Warning: Invalid argument supplied for foreach()"
function ReturnFamilyMembers()
{
var Family = [];
var Table= document.getElementById('FamilyTable');
var RowQuantity= Table.rows.length;
for (var i = 0; i < RowQuantity; i++)
{
var Columns= Table.rows.item(i).cells;
var ColumnQuantity= Columns.length;
Family[i] = [];
for(var j = 0; j < ColumnQuantity; j++)
{
Family[i][j] = Columns.item(j).innerHTML;
}
}
var headers =
{
'Content-type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
};
var FamilyArray = encodeURIComponent( JSON.stringify( Family) );
/*console.info( payload );*/
var xhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
/* Add a callback function to process any response from target url ( Worker.php )*/
xhttp.onreadystatechange = function()
{
if( xhttp.readyState == 4 && xhttp.status == 200 )
{
cbReturnFamilyMembers.call( this, xhttp.response );
}
};
xhttp.open( 'POST', 'Worker.php', true );
for( header in headers ) xhttp.setRequestHeader( header, headers[ header ] );
xhttp.send( 'Family=' + FamilyArray );
}
function cbReturnFamilyMembers($resp,$response)
{
alert($resp + $response);
}
}
And the php side...
$Family = json_decode( $_POST['Family'],true);
foreach($Family as $Array) ---> This line launches the error.
{
foreach($Array as $Value)
{
///object creation
}
}
Thank you in advance. I think Im really stucked here, since Im new to PHP, JS and AJAX, everything seems to happen magically. (Can't really say if Im doing thing's the right way.)
I hope Im being clear enough, or tell me please if I can clarify anything.
--------------------------------------****--------------------------------------
EDIT: Im sorry for the late reply and I thank you for your answers. Im going to update the code, so you can see what I have done so far. (Basically I changed the Ajax Part, to be a POST action like you guys said).
I guess I did not explain the whole thing pretty well, this array must be sent trough submitting a form, this function is called on the "onSubmit" (sorry for the lack of explanation). I came to realize I did not have a member in the $_POST array from php that's called "Family", because I got an error of "Index not found", so, I hid an input in the form and called it that way in the NAME property.
In spite of all that, I keep receiving a non-array like value on the php side, (Actually, when I echo it, it prints a one (1)).
Im starting to think of other way's of passing an array, but that's why I used JS and ajax in the first place.
Im doubting of the
"xhttp.send( 'Family=' + Array );" part... is it really posting the array on the index ['Family'] of the $_POST array?, I wonder.
Maybe the array passed as a value is overwritted by the input of the form (That has no value when submitted, actually)
*************************EDIT,AGAIN*****************************************
Changed the code, and worked perfectly.(Added the Cast to an Array object)
$Family = (Array)json_decode( $_POST['Family']);

I didn't notice last night when I posted my initial comment some of the minor errors with your original function, though others have picked up on them and passed comment above - the function was supposedly sending via POST but there were no parameters sent in the send() method, only appended to the url as you would do for a GET request. Also, though not critical I believe, you were not setting any headers with the request and there also is no callback function.
The altered code below does send the contents from a table as intended over POST
<script type='text/javascript'>
/* callback function to handle response data */
function cbReturnFamilyMembers( response ){
alert( response )
}
function ReturnFamilyMembers() {
var Family = [];
var Table= document.getElementById('FamilyTable');
var RowQuantity= Table.rows.length;
for ( var i = 0; i < RowQuantity; i++ ){
var Columns= Table.rows.item(i).cells;
var ColumnQuantity= Columns.length;
Family[i] = [];
for( var j = 0; j < ColumnQuantity; j++ ) Family[i][j] = Columns.item(j).innerHTML;
}
/* XHR headers to be set */
var headers={
'Content-type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
};
var payload=encodeURIComponent( JSON.stringify( Family ) );
/*console.info( payload );*/
var xhttp=window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
/* Add a callback function to process any response from target url ( Worker.php )*/
xhttp.onreadystatechange=function(){
if( xhttp.readyState==4 && xhttp.status==200 ){
cbReturnFamilyMembers.call( this, xhttp.response );
}
};
xhttp.open( 'POST', 'Worker.php', true );
for( header in headers ) xhttp.setRequestHeader( header, headers[ header ] );
xhttp.send( 'Family='+payload );
}
</script>

I'm not a native JavaScript guru (I prefer something like jQuery when it comes to AJAX etc.), but from what I read in your code you do not receive the expected POST data on the PHP side. Looking at your ajax call I see something weird:
xhttp.open("POST", "Worker.php&Family= " +
encodeURIComponent(JSON.stringify(Family)), true);
xhttp.send();
I see that you are using & instead of ? in the GET request.
If I look at the example code on w3schools it shows me something different:
xhttp.open("POST", "ajax_test.asp", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=Henry&lname=Ford");
Try changing your JavaScript code to send data via POST, not GET.

I was trying to see trough thing's that I missed and added some casting on $_POST (Just in case, you know) to be an actual array, and guess what. It worked like a charm. These are thing's that I really hate about php, but I manage.
So, the code on the PHP side stay's like this...
$Family = (Array)json_decode( $_POST['Family']);
And it does not complain anymore about passing an uncorrect argument on for each.,actually It seem's like it casted the Array's inside of the father Array as well, because the nested for each inside of it worked as expected.
Well, Im a litlle more of ashamed of the amount of time that I lost with this thing, but I thank you all for your help, I greatly appreciate it, and It's actually your answers that led me trough get this thing working, (And get the data sending trough $_POST).

Related

Understanding Ajax requests to update page content when SQL Query Response changes

I am writing a page update which works with PHP to read a SQL database the page echo's the contents in a div section 'track_data'. yet it doesn't do this update idk
I have JavaScript script which I dont really fully understand and hopeful someone could explain its principally the check response section I think is failing ? :
in my PHP page :
<script type="text/javascript">
function InitReload() {
new Ajax.PeriodicalUpdater('track_data', 'fetch_sql.php', {
method: 'get', frequency: 60, decay: 1});
}
</script>
Thanks for looking and hopefully someone undersstands this and can put a smile on my face for the second time today :)
Steps to fix
Thanks for the suggestions of syntax errors. I haven't really got very far with this here are the changes you suggested which I have changed but I still think there is something wrong with last function as it doesn't update div section.
Code in JS file
// Start Clock refresh
// uses new new Ajax.PeriodicalUpdater(
// in main fetch file to trigger the auto update of the page.
// Written by Denise Rose
var gUpdateDiv;
var gContentURL;
var gcheckInterval;
var gcheckURL = "";
var gCurrentCheck ="";
_fetchUpdater('track_data','/fetch_sql.php','/fetch_sql.php',8000);
function _fetchUpdater(updateDiv,contentURL,checkURL,checkInterval)
{
gUpdateDiv = updateDiv;
gContentURL = contentURL;
gcheckInterval = checkInterval;
gcheckURL = checkURL;
setTimeout('check();',gCheckInterval);
}
//Called by _fetchUpdater every (n) seconds determins if content should be updated.
function check()
{
new Ajax.Request(gContentUrl,{method:'get', onSuccess:'checkResponse'});
setTimeout('check();',gCheckInterval);
}
// looks for the response and determines if the div should be updated.
function checkResponse(transport)
{
var content = transport.response.Text;
if(gCurrentCheck != content) {
gCurrentCheck = content;
new Ajax.Request(gContentUrl, {method: 'get',onSuccess:function t() {
$(gUpdateDiv).innerHTML = t.responseText; /*t.response.json()*/}
});
}
}
This is the bit I dont understand
function checkResponse(transport)
{
var content = transport.response.Text;
if(gCurrentCheck != content) {
gCurrentCheck = content;
new Ajax.Request(gContentUrl, {method: 'get',onSuccess:function t() {
$(gUpdateDiv).innerHTML = t.response.json();/*t.responseText;*/}
});
}
}
Method and Issues
What is transport here and what is t? if it stores the contents of the body text from the second in gCurrentCheck and compares to transport version content then why doesn't it update if its different please which it is if the SQL has created a different page?
I did find this https://api.jquery.com/jquery.ajaxtransport/
First Answer not using Ajax
I was given a neat and JS version as an answer, which is not really what I was looking for. I was hopeful to get the one working with one with Ajax but I appreciate your efforts is very kind. I just really wanted to send a refresh to the div area so that the PHP rebuilt the page from the SQL.
I might have been missing the MIT javascript http://www.prototypejs.org/ lol but I dont think it was.
Just to help:
AJAX stands for Asynchronous JavaScript And XML. In a nutshell, it is the use of the XMLHttpRequest object to communicate with servers. It can send and receive information in various formats, including JSON, XML, HTML, and text files. ... Make requests to the server without reloading the page.
Researching
I found this Update div with the result of an Ajax-call but it did not really explain as the OP was using PHP like me not HTML. The answer was given:
$.ajax({
url: 'http://dowmian.com/xs1/getcam.php',
type: 'GET',
data: {id: <?php echo $cam_id; ?>},
success: function(responseText){
$('#update-div').html(responseText);
},
error: function(responseText){
}
});
I dont think above it answered posters question or mine as ajax is a server based push how is this relevant? as if its PHP driven the needs a refresh at server to refresh the contents not to provide new html. It is this refresh I am not interested in to re-copy PHP code elsewhere in JS as its already in my PHP. Does that make more sense?
Update
I did find a bracket missing and a set of single quotes inserted by editor. Which I have updated above but there was no significant change.
Cheers Nicolas . I am still hopeful that someone knows about Ajax as it sits underneath these technologies. I have a server side PHP file that I was hoping to use AJAX to pull just the PHP from the section it was pointing to an gUpdateDiv . As its derived from the server and created on the fly from SQL. I dont see how your answer would help push this data back in to the from the server . The $(gUpdateDiv).innerHTML was supposed to be acted upon not the whole page . What I am unsure of is how a trigger from this can update timer just this $(gUpdateDiv).innerHTML . I am also not aware if a server based refresh would do this or if the transport id provided from the file would be able to deliver just that . I think I am missing something a vital part that I dont have or have grasped yet. The reason there is two timers is effectively it checks the same file at a different point in time as its created by PHP it might be different from the first if it is i.e. the SQL data has changed, I want this to update this $(gUpdateDiv).innerHTML with the data which it compared it to the second 'Get' in the second request. It sounds, simple in practice but have got stuck comparing two versions and insuring second version gets used .
Further update placing an alert in the Javascript file did not pop up like it does here https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_alert however the same alert in the initiating PHP worked fine and created the alert. called the same function from the main PHP nd the alert occurred so the JavaScript is running next visit F12 on the page to see if there is any warnings or errors. Ok after adding JQuery which I thought I had added this started working however It is not doing what i Expected it to do. As the contained both text and graphics created by PHP I expected this all to be updated The graphics are not the text is any ideas? .
Further to the image problems I placed an extra line to update the image however I used this too in PHP
<script type="text/javascript">
//initpage() ;
function updateArtworkDisplay() {
document.querySelector('#np_track_artwork').src = 'images/nowplaying_artwork_2.png?' + new Date().getTime();
}
</Script>
But it didnt work to update the image in php?
<div id='outer_img'><img id='#np_track_artwork' src='/images/nowplaying_artwork_2.png' alt='Playing track artwork' width='200' height='200'></div>
in js change
/ looks for the response and determines if the div should be updated.
function checkResponse(transport)
{
var content = transport.response.Text;
if(gCurrentCheck != content) {
gCurrentCheck = content;
new Ajax.Request(gContentUrl, {method: 'get',onSuccess:function t() {
$(gUpdateDiv).innerHTML = t.responseText; /*t.response.json()*/}
});
updateArtworkDisplay(); // fire up the redraw in php file.
}
}
Nearly there it does almost what it needs to apart from the redraw which is not happening
// Start Clock refresh
// uses new new Ajax.PeriodicalUpdater(
// in main fetch file to trigger the auto update of the page.
// Written by Denise Rose
var gUpdateDiv="";
var gContentURL="";
var gcheckInterval=0;
var gcheckURL = "";
var gCurrentCheck ="";
_fetchUpdater('track_data','/fetch_sql.php','/fetch_sql.php',8000);
function _fetchUpdater(updateDiv,contentURL,checkURL,checkInterval)
{
gUpdateDiv = updateDiv;
gContentURL = contentURL;
gcheckInterval = checkInterval;
gCheckURL = checkURL;
setTimeout('check();',gcheckInterval);
}
//Called by _fetchUpdater every (n) seconds determins if content should be updated.
function check()
{
new Ajax.Request(gCheckURL,{method:'get', onSuccess:'CheckResponse()'});
setTimeout('check();',gcheckInterval);
}
// looks for the response and determines if the div should be updated.
function checkResponse(transport)
{
var content = transport.response.Text;
if(gCurrentCheck != content) {
gCurrentCheck = content;
new Ajax.Request(gContentUrl, {method: 'get',onSuccess:function t() {
$(gUpdateDiv).innerHTML = t.responseText; /*t.response.json()*/}
});
$time = new Date().getTime();
new Ajax.Request('outer_img', {method: 'get',onSuccess:function s() {
$('outer_img').innerHTML = "<img id='#np_track_artwork' src='/images/nowplaying_artwork_2.png?t='"+$time+" alt='Playing track artwork' width='200' height='200'>"}
});
}
}
GIVEN UP WITH THIS PLEASE DELETE MY PERSONAL INFORMATION AND POSTSript-fetch-async-await/

Sending array to PHP using XMLHttpRequest (pure JS)

I'm attempting to send an array from JS to PHP using AJAX.
What seems to be happening is that the request is going through and is successful, but no data is received on the server (my test.php script needs the data from this array). Here is what I have so far...
Javascript
myButton.onclick = function() {
var xhr = new XMLHttpRequest();
xhr.open("POST", "test.php", true);
xhr.onreadystatechange = function () {
if (xhr.readyState==4 && xhr.status==200) {
console.log("Done. ", xhr.responseText);
}
}
//xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send('myArray='+JSON.stringify(myArray));
};
test.php
<?php
//$myArray = json_decode($_POST['myArray']); //Undefined index
print_r($_POST);
Note, myArray is not shown in the above code, but it is a valid array.
I've searched around SO (which led me to adding the 'setRequestHeader' in), as well as the wider internet. However, this has made no difference and I seem to be going round in circles. When I print $_POST, it's always an empty array.
I'm sure there's something I'm missing/misunderstanding.
Edit
As requested...
var myArray = ["John", "Jill", "James"];
I've also attempted this with an array of booleans, as well as an associative array/object.
Edit 2
As requested, adding screen shot from dev console...
you can use formData :
let data = new FormData();
let values = [1, 2, 3];
data.append('myArr', JSON.stringify(values));
// send data to server
and in php use json_decode :
$Values = json_decode($_POST['myArr']);
another way is to create HTML checkbox or select elements with javascript , assign values , serialize them and send them to back-end .

Accessing and decoding JSON sent from JavaScript to PHP

So I have a form, I took the contents of its inputs, threw them into an array, had it made into a JSON and then sent it to PHP so it can in turn decode and enter it into a database. I know it'd be easier to just use a <form method="POST" action="phpfile.php"> but I can't have this redirecting to another page, especially since my PHP is not embedded into HTML, instead it handles things offsite. Otherwise it'd be simpler to just use $_POST["name"] to get what I need. Nonetheless, this page in particular is supposed to create the user, receive a server response, that the user has been entered into the database and then is given an alert with a button to be redirected to the main page.
So anyway here are the relevant sections of this whole process.
JavaScript:
window.onload = function findSubmitButton() {
var button = document.querySelector(".send_info").addEventListener("click", serverInteraction);
}
function serverInteraction() {
var xmlhttp;
var inputArray;
var finalArray = [];
var JSONArray;
if (window.XMLHttpRequest){
xmlhttp = new XMLHttpRequest();
} else if (window.ActiveXObject) {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} else {
throw new Error("Your browser is not compatible with XMLHTTP");
return false;
}
inputArray = document.querySelectorAll("input[type=text]");
for(var i = 0; i < inputArray.length; i++){
finalArray[i] = inputArray[i].value;
}
console.log(finalArray);
JSONArray = JSON.stringify({finalArray: finalArray});
console.log(JSONArray);
xmlhttp.open("POST","phpFiles/sendUserInfo.php", true);
xmlhttp.setRequestHeader("Content-type","application/json");
xmlhttp.send(JSONArray);
}
PHP:
<?php
$finalArray = json_decode($_POST['finalArray']);
var_dump($finalArray);
?>
That var_dump simply returns a null and using echo gives me nothing, except a warning that my array variable isn't initialized through XDebug. I'm not quite sure what I'm doing wrong here, I've been following this just like the tutorials tell you to do it, and isn't generating the array. I've also tried $_POST['JSONArray']without any luck in case that was how it was supposed to go. Also tried file_get_contents('php://input') which sends an empty string as well.
You can't get your data from $_POST if you put JSON in your post body.
see this question Receive JSON POST with PHP. php can't handle application/json properly.
For your var_dump is empty, try this
var_dump(file_get_contents('php://input'));
var_dump(json_decode(file_get_contents('php://input'), true));
you will see your data.
And if you send your data without change it to JSON, you will get wrong data.
eg: your finalArray is ['a','b','c'] and you send it directly.
var_dump(file_get_contents('php://input'));
you will see php got string a,b,c instead of ['a','b','c']
So if you want to use $_POST to receive data, you need to use application/x-www-form-urlencoded. you can use jquery to do it. see http://api.jquery.com/jquery.ajax/
$.ajax({
method: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
})
.done(function( msg ) {
alert( "Data Saved: " + msg );
});
it will serialize your js object into x-www-form-urlencoded and php will handle it properly.
use chrome's dev tools, switch to network and see the request payload and response would be helpful for you.
You are bypassing $_POST by sending the the data as "Content-type","application/json" .
The data will instead be set in the body of request and can be retrieved using file_get_contents("php://input")
For further discussion see file_get_contents("php://input") or $HTTP_RAW_POST_DATA, which one is better to get the body of JSON request?
Generally there is no need to send your data as json to php

How to parse xml with js or jquery, when fields are not known in advance?

I have been searching for the past hour and have not found a solution that is well suited to my situation. I have an event registration form and in order for users to have the form auto populated they can specify an id from a previous registration. There are over 20 fields.
Everything is working pretty well. I have a PHP script that creates an xml response for ajax. The xml is of form
<response>
<field1>f1</field1>
<field1>f2</field1>
etc
</response>
My javascript is
$.ajax({
type : "POST",
url : "myscript.php",
data : $(this).serialize(),
success: function(xml){
$("#field1").val($("field1",xml).text());
$("#field2").val($("field2",xml).text());
}
})
Above works fine but I don't want to manually write out each form field assignment. I want to do it in a loop. So something like this in the success function:
var fields= xmlResponse.getElementsByTagName("response");
for (i = 0; i < fields.length; i++) {
// not sure what to put here...
}
In the for loop I have to index in to the node name and value so that I can simply have a statement that would be of this form: $("#"+fields[i].nodename).val($(fields[i].nodevalue,xml).text());
I tried
$("#" + fields[0].childNodes[i]).val(fields[0].childNodes[i].nodeValue);
But that did not return the values.
Any idea on how best to do this? I feel like I am very close to having this working! Thanks!
You can use $.parseXML, and then loop over the elements with .each().
var $xml = $.parseXML(xml);
$("#response", xml).children().each(function(i, e) {
var field = e.tagName;
var value = e.innerHTML;
$("#" + field).val(value);
});
You're on the right track. What it comes down to is that when you parse an XML file, the parser doesn't care what the fields are, it'll parse it as it sees it. You would basically have to tell the script to pull certain tags with certain text. As far as I know, this is best done using the .tagName property and the tag's value and storing it in an object.
var data={}
$(this).children().each(function() {
data[this.tagName]=$(this).text();
})
You can see how this would work here:
http://jsfiddle.net/dpK7x/1/

AJAX Send POST Variables to PHP

I am used to sending AJAX requests with jQuery. I now find myself with the task of having to send them using 'vanilla' JS. Using my limited knowledge, I managed to get everything working except for passing the data along with the request. The two variables that are supposed to be being passed along are always filled in as NULL in my database. Every example I have been able to find on here shows the jQuery way, which I have no problem doing.
Can anyone tell me what I am doing wrong? I assume it has something to do with the format of the data, but cannot for the live of me figure it out.
Here is the code for the request. The request object is built in the createXMLHttp() function.
var xmlHttp = createXMLHttp();
var data = {Referrer: document.referrer, Path: window.location.pathname};
xmlHttp.open('post', '/PagePilotSiteHits.php', true);
xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xmlHttp.send(data);
var data = {Referrer: document.referrer, Path: window.location.pathname};
function buildQueryString(data)
{
var dataKeys = Object.keys(data);
var queryString = "";
for (var i = 0; i < dataKeys.length; ++i)
{
queryString += "&" + dataKeys[i] + "=" + encodeURICompenent(data[dataKeys[i]]);
}
return queryString.substr(1);
}
xmlHttp.send(buildQueryString(data));
This should do it. The data needs to be passed as a querystring. This functions will create a querystring from the data object you've provided and encodes the uri components as mentioned by #AlexV and #Quentin.

Categories

Resources