jQuery to PHP and back again! - php

I'd like to pass content back and forth from PHP to jQuery and vice versa. I'm not sure if I fully understand the best way to go about this and am hoping for some best advice and clarification.
Below is an example of something I'm trying to do. The PHP lists the files in a directory (whose path is passed to it from jQuery), stores them in an array, then passes them back to jQuery. I'd like to use the values in that array for various purposes but really I just want to understand passing information back and forth between the two, wether it's from an array, or just a plain variable. Merci beaucoup!
The PHP:
$files = array();
$dir = ($_POST['dir']);
$count = 0;
if ($handle = opendir($dir)) {
while (false !== ($file = readdir($handle))) {
if ($file != "." && $file != ".." && strpos($file, '.jpg',1)) {$count++;
$files[$file] = $file;
}
}
closedir($handle);
}
echo json_encode($files);
?>
The jQuery:
$(document).ready(function(){
$('a').click( function(e) {
e.preventDefault();
$.post("php.php", 'path/to/directory/',
function(data) {
alert(data);
}, "json");
});
});

If I read your question correctly, you're not really looking for tips on this specific code, but more for comments about the process of transferring data back and forth between PHP and jQuery. Let's look briefly at JSON itself, and then look at each side of the communication.
JSON
JSON is a simple way of representing collections of data in a string format that is pretty easy for both humans and computers to read. You can get the full description at http://www.json.org/ but it basically boils down to:
data is enclosed by { and } characters
data is in the format string : value, where the string acts as a reference label
string is in the format of ", followed by any unicode char except / or ", followed by another quote
value can be another string, a number, a complete data object, a boolean value, or an array of some set of the above values
an array is of the format [, followed by a comma separated list of values, followed by a ]
PHP
On the php side, you are receiving a page request and using the attached parameters to decide how to process the page. For a JSON app, that means loading the data into an array, and then the json_encode() function does the grunt work for converting that array into JSON format. The rest of the app would work just the same if you manually created the JSON as a string, though obviously this would make for a lot more work in the PHP code for you. Hence the helper function :)
jQuery
On the jQuery side, the call to $.post() issues an AJAX request, to retrieve a page from the server. In this case, you are sending a request to php.php.
The second set of parameters in the $.post() call is a collection of parameters, which should consist of { followed by comma-separated sets of: a label, then a colon, then a value. Once you have specified all parameters, close the collection with a }. Note that though this is similar to a JSON string, it is not JSON. The label does not have quotes around it the way JSON requires. Any string values, however, do need quotes.
The third parameter of the $.post() call is a function that will be automatically applied to the data that is received from the page request. The results of the function are automatically loaded into whatever variable you specify in the function definition, and you are able to use that data within the function, pretty much as you please. In your example, you simply sent the data to an alert box, but you can do much more with it. You could actually parse this as a JSON collection and perform various actions based on the contents of individual components from within the JSON (which, ultimately, means that you are directly acting on individual values from the original php array).
The fourth parameter on the $.post() call is the data-type. It isn't required, however using it is required if you want to access the json collection as more than just a string. With it, you can specify that the type of data you are returning is json, by simply including "json". If you have done this, you can access the elements of the JSON collection directly within the third parameter function, by referencing their label.
Here's an example of a complete JSON $.post() call:
$.post("test.php", { "func": "getNameAndTime" },
function(data){
alert(data.name); //pretend it's John
console.log(data.time); //pretend it's 10:05am
}, "json");
So here, an ajax request is sent to test.php with the parameter func="getNameAndTime" which the php uses to determine that it should return a json-encoded collection of the form {"name":"John", "time":"10:05am"}, and then the response reaches the function specified to first alert() with the value "John" and then log "10:05am". Again, the only reason that data.name and data.time works in this function is because we specified that json was the return type in the fourth parameter.

The code is correct except for this line in the jQuery:
$.post("php.php", {dir: 'path/to/directory/'},
By the way, it looks like your request is idempotent, so consider using GET instead of POST.

Related

Convert key-value JSON to object and refer individual values directly

I am making a web app. In one part of it, I have JS send a string(in json format) to PHP.
The value php receives is:
{"date":"24-03-2014","Cars":["Cheap","Expensive"]}
Now, this is saved in a variable $meta. The problem I am facing is, as to how do I convert this string into an object and reference each individual entry separately.
I have tried json_decode and json_encode
and then I have referenced each variable using $meta.["date"] and $meta.date but nothing seams to work. I am getting just { as the output.
What's the correct way to do this?
$str = '{"date":"24-03-2014","Cars":["Cheap","Expensive"]}';
$obj = json_decode($str);
echo $obj->date;
// 24-03-2014
Usually a $my_obj = json_decode($_POST['jsonstring'], 1); (true supply means it'll be returned as an assoviative array) should be the way to go. If I were you I'd probably try a var_dump($my_obj); to see what actually comes through. If it doesn't work you'll want to make sure that you correctly submit a valid json string, e.g. JSON.stringify();
You should check out the PHP doc page for json_decode here.
By default, unless you pass true as the second parameter for json_decode, the function call will return an object, which you can access the members of by using:
$meta->date
The arrow operator will allow you to access object values, not the square brackets or a dot.

null on json data

I am trying to parse this json data from the url but i get NULL how do i fix this issue.
$source = file_get_contents('http://partners.socialvi.be/e414f702cf3db89a2fe58066bbab369d65b6a058/activities/available.json');
$json = json_decode($source);
var_dump($json);
That's because the API returns the data in JSONP format, not pure JSON. Notice the surrounding onSVJson([]). You'll either have to strip this out, or read the API documentation and try another request format. My guess would be that leaving out the final &callback=onSVJson should do the trick.
That's because if you call the url (go to http://partners.socialvi.be/e414f702cf3db89a2fe58066bbab369d65b6a058/activities/available.json?network_user_id=3459874&max_activities=9&callback=onSVJson with your browser) the json that is returned has no values
Remove the last part of the URL (&callback=onSVJson) and it'll work.
Many APIs offer a feature called JSONP, that allows the JSON to be passed to a callback function, in order to simplify access via cross domain JavaScript. But for PHP you don't need that.
The name of the callback function is typically specified using the callback GET parameter. If you leave that out, no callback function is used - just plain JSON.

jQuery serialize issue with php foreach

$("#doStatus").click(function()
{
var serialized = $("#formStatus").serialize()
$.get("<?echo $site['url'];?>modules/yobilab/tuitting_core/classes/doStatusBox.php", serialized);
window.setTimeout('location.reload()', 1000);
return false;
});
This code will return something like this:
tuitting=test&f%5B%5D=2&f%5B%5D=4&f%5B%5D=8&t%5B%5D=2&t%5B%5D=3&t%5B%5D=4
Where tuitting(the first value) is the value of the textarea, then we have:
-f this is the name of somecheckboxes that have the same names but different values
-t other checkboxes, same names, different values
As you may see the serialized function for "f" and "t" returns strange values, when they should only be simple number, like tuitting=test&f=1&f=3&t=9&t=10
Now when the ajax call the doStatusBox.php file nothing happens.
The doStatusBox.php file is made by a simple foreach php loop.
It will take the below variables:
$_GET['tuitting']
$_GET['t']
$_GET['f']
Foreach `$_GET['t'] and $_GET['f'] the loop will insert the relative values into the database.
This is not working at all. The php foreach can not recognize the results given by the jQuery serialize function and does not do simply anything.
What is the problem?
I should use another function instead of foreach?
Or the problem is in the jQuery serialized function?
Please help me.
`
Since we cannot see your HTML code, I can't say for sure what the problem is, but I suspect it's one of two problems:
(most likely) - your checkbox fields need to have a [] after the name. Example: name="t[]". If all of your checkboxes are name="t", then when multiple are posted, PHP will only see one of them. However, if you put brackets at the end of the name PHP will recognize the collection of values as an array that you can loop through.
(less likely) - the PHP script that receives this data should run urldecode() on the data. Example: $tuitting = urldecode($_GET['tuitting']);
Hope this helps!

Erratic behaviour when comparing PHP imploded arrays with form field values using JavaScript

I've got a PHP Object, whose properties are initialized the following way:
$this->contact = implode(PHP_EOL,$description->getContact()) . PHP_EOL;
The only exceptions are two properties named version and bugs.
This object is then encoded into a JSON object and passed into the following javascript, which compare the JSON object with value from a form.
function compareEntry(data){
var dataProperties = ["version", "bugs", "scenario", "exception", "instruction", "sources", "risks", "test", "contact"];
var hasChanged = false;
for(var i = 0; i < dataProperties.length; i++){
var dataProperty = dataProperties[i];
alert("Original: '" + data[dataProperty] + "'\nModified: '" + document.myform[dataProperty].value + "'\nTest Value: " + (!data[dataProperty].localeCompare(document.myform[dataProperty].value)));
if(!data[dataProperty].localeCompare(document.myform[dataProperty].value)){
hasChanged = true;
}
}
[...]
In the exception of version and bugs, all other properties are compared with the value in the textarea.
The form fields are initialized with the value of the PHP object. When I submit the form the function is called. If I submit the form without changing any value, it still give me a false when comparing a property with the value of a textarea. Why and how could I correctly compare them?
Notes: The PHP Object is a reflection of a MySQL entry which was created with the same form. In between, the information was encrypted and decrypted. But it shouldn't play a role, because the PHP/JSon object and the initial value of the form are from the same source.
EDIT
After the explanation of Frode, I changed my testing statement to:
data[dataProperty].localeCompare(document.myform[dataProperty].value)!=0
But afterwards I noted two discrepencies.
Properties version and bugs which until then returned true when tested return now false. But in the contrary to the other properties, I don't manipulate the values when I'm retrieving them from the database. The value of the property version is stored in a select tag in the form.
And weirder is, when I'm changing one of the value in the textarea, instead of giving me false, it gives me true.
It occured to me that it may be due to the implementation of javascript of the browser I use. But the result I got is not quite as I expected it. Whereas, I've got the described behaviour in Firefox and Chrome, IE and Opera throw always false (with the notable exception of the comparing the version, which gave me true in IE, although he couldn't retrieve the value of the select tag).
Should I maybe use some other method to compare my strings?
EDIT 2
After taking the suggestion of WoLpH, I changed the test condition to:
data[dataProperty].trim() document.myform[dataProperty].trim()
Where trim() is the function described in this other question. And the result are the inverse of what I had in the first EDIT. Except for Chrome who seems to assign it's boolean in random. There seems to be something really wrong in my data in a way.
Here is an example of a JSON object as I can see it in Firefox (variable data in the code snippet).
{"version":"REL-773","bugs":"20831","scenario":"THIS IS A TEST\r\n\r\nThis is the what happens: stuffs.\r\n","exception":"N\/A\r\n","instruction":"1. First Step.\r\n2. Second Step.\r\n2. Third Step\r\nIt is longer.\r\n4. Fourth Step.\r\n5. Fifth Step.\r\n6. Sixth Step.\r\n","sources":"me\r\n","risks":"High risks as it is just for testing of the web application.\r\n","test":"1. Select an entry\r\n2. Change some data such as <HOME>\/path\/\r\n3. See if the application run as expected!\r\n","contact":"me#web.de\r\n"}
EDIT 3
Using the function escape() to escape all special characters of the two strings, I noticed that in the character %OA is written as %OD%OA in the JSON object. It made me suspect that my trimming function doesn't replace correctly the \r\n by \n. (trimming function that I added after the suggestion of the posters here.)
Here is the function I use:
if(typeof(String.prototype.trim) === "undefined")
{
String.prototype.trim = function()
{
return String(this).replace(/^\s+|\s+$/g, '').replace(/\r\n/g,"\n");
};
}
First, Disclaimer: I have the feeling that maybe this isn't the definite answer but more of a workaround. As this is the only way I could deal with this problem.
Now, since I had posted this question, I learned that client-side form validation is not enough. Not only it not enough, but in my case it is not needed as it wouldn't bring anything in the user experience to know that a value has been changed. It is much more interesting for the user to know that a value is not well formatted or just plain wrong. So I migrated the comparison check to the server side.
First I encase my PHP information in a json string, being sure to escape all the relevant characters. I first ensured that the quote symbol was escape correctly, and then I replaced characters which could be problematic by there unicode equivalent, before putting the resulting string in a hidden input of my form.
//escaping ",' and other throublesome characters properly for json
$json_string = str_replace('\'', "\\'", json_encode($objEncasing));
$json_string = str_replace(array('\\"', '\\\'', '&','<','>'), array('\\u0022', '\\\u0027', '\\u0026', '\\u003C', '\\u003E'), $json_string);
echo "<input name='json' type='hidden' value='".$json_string."' />";
One should note that the json object correspond to the information before any change are made in the form, thus why the json string is formatted in PHP. The form information is then sent through POST to a new script which will do all the necessary work.
Now first thing I do in the receiving script, is retrieve the json variable, but one should not forget to check for magic quotes:
if(get_magic_quotes_gpc()){
$json_string = stripslashes($_POST['json']);
}else{
$json_string = $_POST['json'];
}
Now to convert the json object into an array and the you can compare it to the $_POST array (with the exception of the json value):
if(!empty($json_string)){
$json_encasing = json_decode($json_string, true);
$gotChange = false;
foreach($_POST as $key => $value){
if($key != "json"){
//Compare the value, if something change set $gotChange to true
$value = stripslashes($value);
if($value != $json_encasing[$key]){
$json_encasing[$key] = $value;
$gotChange = true;
}
}
}
if($gotChange){
//Do your stuff
}
}
As I'm doing that on my Server, I don't need to anticipate several different behaviour. So my advice is, if you can help it, do your stuff server-side.
Javascript's string.localeCompare returns 0 if the strings compared are identical, and -1 or 1 otherwise. So your if clause:
if(!data[dataProperty].localeCompare(document.myform[dataProperty].value)){
hasChanged = true;
}
.. will in fact set hasChanged to true when the strings are equal. Try removing the ! and see if it behaves as you expect.

JQuery .get() only passing first two data parameters in url

I have a $.get() call to a PHP page that takes 4 GET parameters. For some reason, despite giving the $.get() call all 4, it only passes the first two. When I look at the dev console in chrome, it shows the URL that gets called, and it only passes action and dbname. Heres the code:
$.get('util/util.php', { action: 'start', dbname: db, url: starturl, crawldepth: depth }, function(data) {
if (data == 'true') {
status = 1;
$('#0').append(starturl + "<ul></ul>");
$('#gobutton').hide();
$('#loading').show("slow");
while(status == 1) {
setTimeout("update()",10000);
}
} else {
show_error("Form data incomplete!");
}
});
and heres the URL that I see in the developer console:
http://localhost/pci/util/util.php?action=start&dbname=1hkxorr9ve1kuap2.db
** EDIT **
I have been informed that I need to encode the URL that I am trying to pass through the header. How would I go about encoding it in javascript, and decoding it in php?
Are you sure that the starturl and depth variables are defined? A simple alert() before the $.get() will be enough to check.
In regards to your edit, you can encode strings in JavaScript with the encodeURIComponent function. And decode it back again in the PHP with urldecode. They both take one string argument.
Probably you will need to check whether your input strings are properly quoted. Internally jQuery will build the paramter string out of the parameter map you specified using its param() method. This method will construct an object of the keys and values, which will likely not be parseable if you quoted your keys and values incorrectly.
# Felix Kling: jQuery automatically encodes keys and values of the parameter string with encodeURIComponent.

Categories