Jump to content

How best to send PHP data to a JavaScript client


NotionCommotion

Recommended Posts


I am successfully doing this, however, I believe I am doing it wrong.  I am currently doing the following.  How should I be doing this?  My thought is getObject.php should return JSON, not JavaScript, but I don't know how to assign the received JSON to the myObj variable.  Thanks

 

PS. If there is a special way to do so when using Twigs, please advise.



<script type='text/javascript' src='getObject.php?id=123'></script>


<script type='text/javascript'>
  console.log(myObj);
</script>


 

getObject.php



header("Content-type: text/javascript");
$myObj=array('foo'=>'bar'); //Actually, queries DB using $_GET['id'], and gets a bunch of data
exit('var myObj='.json_encode($myObj));


Edited by NotionCommotion
Link to comment
Share on other sites

What are you ultimately trying to accomplish?

 

The client later uses the data to perform various given tasks.  For instance, maybe the myObj consists of ten arrays.  User clicks the "three" button, and the data in array 3 is displayed.  So, my JavaScript needs to be able to access myObj.array3.

 

My thought of doing it this way instead of individual Ajax calls upon each click is that they will be clicked more than once on a given page load, and I want to reduce the calls to the server.

header("Content-type: text/javascript");
$myObj=array(
 'array1'=>array(1,2,54,213,54),
 'array2'=>array(8,4,213,54),
 'array3'=>array(4,2,54,213,54),
  ...
 'array10'=>array(77,2,54,23,54)
);
exit('var myObj='.json_encode($myObj));
Edited by NotionCommotion
Link to comment
Share on other sites

Generating dynamic JavaScript code is the worst possible choice and a sure way to get nasty bugs and huge security vulnerabilities. In a properly configured environment, this code wouldn't even run. Appearently you don't have such an environment, so the code does run. But that's no excuse for actually using it.

 

There are exactly two ways to get PHP values into JavaScript:

  • Ajax. This is by far the cleanest, most robust and most secure solution. Use it. I'm not sure why you think you need a separate Ajax request for each click. You don't, just make a single request for all data when the document is loaded.
  • A hidden HTML element which holds the escaped JSON document so that JavaScript can parse the data. This lets you save the one Ajax request, but it's hardly worth the trouble. Don't do this unless you have hard facts which prove that Ajax is not an option.
Link to comment
Share on other sites

I can only show what I do using jQuery. I don't know how it works otherwise:

 

SERVER (whatever.php)

echo json_encode(array(
	'response' => 'success'
	'a' => 'one',
	'b' => 'two',
	'c' => 'three'
));

JS

$.ajax({
	type: 'post',
	data: {}, // You'd normally put stuff in here
	cache: false,
	url: '/whatever.php',
	dataType: 'json',
	success: function(response){
		if( response.status && response.status == 'success'){
			alert(response.a);
			alert(response.b);
			alert(response.c);
		}else{
			if(response.message){
				alert(response.message);
			}else{
				alert('Error on server.');
			}
		}
	},
	error: function(){
		alert('Network error.');
	}
});
Link to comment
Share on other sites

 

Generating dynamic JavaScript code is the worst possible choice and a sure way to get nasty bugs and huge security vulnerabilities.

 

Yes, I know the nightmare of dynamically generated JavaScript.  I remember doing it and thinking I was so smart.  I soon learned the error of my ways.  The limited dynamically generated JavaScript used to populate a variable has much less of the troubleshooting issues, however, I expected it wasn't best practice thus asked the question.  Just curious, on this limited use of just setting a variable, what are the security vulnerabilities?

 

 

 

Ajax. This is by far the cleanest, most robust and most secure solution. Use it.

 

 

Will Ajax's asynchronous behavior cause problems?  I might have script in other files that needs access to the object, thus putting it in a callback will not be so simple.

Link to comment
Share on other sites

Just curious, on this limited use of just setting a variable, what are the security vulnerabilities?

 

The problem is that you cannot make sure that the code will just set a variable. It's a full-blown script which can do anything. So if any of the dynamic values leaks into the code, you immediately have a cross-site scripting vulnerability or at least a bug.

 

And preventing this is much harder than preventing, say, an SQL injection. Many programmers don't even understand the parsing procedure.

 

For example, in plain HTML, any occurence of the term “</script>” within inline code immediately terminates the current script context and allows the user to create arbitrary HTML elements:

<script>
	var str = "I'm just a harmless string. Or maybe not: </script><script>alert('XSS')</script><script>";
</script>

On the other hand, XHTML allows the user to circumvent common escaping mechanism with HTML entities:

<?php

header('Content-Type: application/xhtml+xml');

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>XSS</title>        
    </head>
    <body>
        <script type="text/javascript">
            var str = "I'm just a harmless string. Or maybe not: ";alert('XSS');//";
        </script>
    </body>
</html>

And those are two of the more harmless examples. Who knows what other ideas people come up with?

 

Trying to safely insert values into a JavaScript context is a battle against weird parsing rules, crazy browsers and very creative individuals. I wouldn't try it.

 

 

 

Will Ajax's asynchronous behavior cause problems?  I might have script in other files that needs access to the object, thus putting it in a callback will not be so simple.

 

Why not? When the data is needed for the first time, it's retrieved and cached in a global variable. All later function calls can use the cached result.

Link to comment
Share on other sites

Thanks Jacques1,  I see your point.  Maybe with great effort I can prevent it, but why bother and just do it right the first time.

 

Why not? When the data is needed for the first time, it's retrieved and cached in a global variable. All later function calls can use the cached result.

 

I definitely crossed outside of the scope of PHP, however, still would appreciate comments on the following scope.  How do we know myObj.myProp is defined when someFastScriptWhichAccesses_myObj.myProp.js is executed?

<!DOCTYPE html>
<html>
    <head>
        <title>Example</title>
        <script type='text/javascript'>
            var myObj={};
            $.get( "someSlowURL.php", function( data ) {
                myObj.myProp=data;
                }, "json" );
        </script>
        <script src="someFastScriptWhichAccesses_myObj.myProp.js" type="text/javascript"></script>
    </head>
    <body></body>
</html>



 

Link to comment
Share on other sites

How do we know myObj.myProp is defined when someFastScriptWhichAccesses_myObj.myProp.js is executed?

You don't. Whatever parts of the other script need myObj will have to be wrapped in an accessor function which executes a callback once the data is loaded. When called the first time there may be a slight dely but any subsequent calls would just use cached data and run the call back immediately.

 

(function(){
	var myObj;
	var $xhr = $.get('someSlowURL.php', 'json').done(function(jsonObj){
		myObj = jsonObj;
	});
	window.getData = function(cb){
		$xhr.done(function(){
			cb(myObj);
		});
	};
}());

//Later on:

getData(function(data){
	//Access data
});
The above creates an Immediately Invoked Function which creates the XHR request to load the data and when complete assigns it to the myObj variable.

 

Then it creates a global function called getData which accepts a callback. That function will take that callback and execute it when the XHR request is complete and pass the myObj variable as the first argument.

 

For more information about the .done() method being used, look at jQuery's Deferred Object api.

  • Like 1
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.