how to pass variable from php template to javascript [duplicate] - php

This question already has answers here:
How do I pass variables and data from PHP to JavaScript?
(19 answers)
Closed 8 years ago.
I have a page where I want to display some points on map. I have small templates (like Smarty, but lighter) and there in template I have variable $points, that consists of coordinates of points I need. I need to pass them to javascript (because only javascript can render that map with points).
I have 3 variants of doing it. Can you tell, what is best?
1th way: (Template inserting javascript-tags with global variable)
tpl.php file:
<script>
MAP_POINTS = <?php echo json_encode($this->points); ?>;
</script>
.js file
function renderMap(){
var points = MAP_POINTS; // using global. Is it really bad? or who cares? =))
}
2nd way: (Passing variable through the HTML element)
tpl.php.file
<input type="hidden"
value="<?php echo json_encode($this->points); ?>"
id="map_points_container">
.js file
function renderMap(){
// without globals, but needed to be parsed on local side
var points = $.parseJSON ( $( "#map_points_container" ).val() );
}
3rd way: (AJAX-way)
I don't pass $this->points from template file at all. I have another .php file that handles all my AJAX requests:
Ajaxing.php
function get_map_points($params){
// some operations
return json_encode ($map_points);
}
And than on local side I'll have something like this:
.js file
$.post ( 'ajaxing.php', params,
function(points){
renderMap(points);
}, 'json');
The third way is usual, but if I already pass some values from template to local page, then I can pass and map points too. In fact, I don't need to make another request for only this map points (that's why I don't like third way)
But may be you can advise me another way? a better way?
The way I choosed:
1th way with little remarks. All my 'map-rendering' code is in another file and it's like:
$(function(){
MAP_APP = {};
MAP_APP.some_prop = null; // some properties
MAP_APP.some_method = function(){}; // some methods
});
So in template file I only have to extend my MAP_APP object:
<script>
MAP_APP.points = <?php echo json_encode($this->points); ?>;
</script>
Yes, global variable. But it's like namespace of whole application.
Thanks to everybody.

The first way is definitely the least complicated and fastest.
The second one adds an additional processing step (the parseJSON()) that isn't necessary.
The third way is good if you're dealing with lots of data that is optional (i.e. is needed only if the user requests it, and it isn't 100% sure whether that will happen) or dynamic. It creates a new request though, and is not going to be immediately available.
If you don't want to use globals, you could e.g. wrap your JavaScript functions into an object, and populate an object property from PHP:
<script>
MyObject.MAP_POINTS = <?php echo json_encode($this->points); ?>;
</script>

There is another funky way of passing variables in a js external file :)
Your PHP file:
<script type='text/javascript' src='script.js?id=0&some=<?php echo $whatever?>'></script>
and inside your script.js you can retrieve those values:
var scripts = document.getElementsByTagName('scripts');
// get your current script;
for (var i=0,l=scripts.length;i<l;i++){
if(scripts[i].src.indexOf('script.js') !== -1) { // or your script name
var query = scripts[i].src.substr(scripts[i].src.indexOf('?')+1);
// now you can split the query and access the values you want
....
}
}

The first one is most efficient and fastest. The second one is funky. The third one is also fine.
The first because it does not require any other requests. The second one is a bit odd, I would not use that kind of constructs, but that does not mean you can't. The third one is also fine, but you should think about if AJAX is the way to go. If you application requires multiple requests for points for different locations, then it might be the most efficient way to go.

I would go with your second method since you don't want to use AJAX for it (and it seems odd to use AJAX for something you already have in the current page). You want to limit the number of global variables in your JavaScript because everything in your JavaScript will create an instance of each global variable and thus decrease your performance.
I forgot the name of the person, but the man who was heading on optimization at Yahoo! and then went to work for Google gave a lecture about JavaScript optimization, and this was one of his points.
EDIT: Found the link: http://sites.google.com/site/io/even-faster-web-sites

Speed wise 1st way is the best way.
But the best way is to create an XML output from PHP and loading that xml into Javascript via Ajax. The best example of this is article given on google maps documentation - http://code.google.com/apis/maps/articles/phpsqlajax_v3.html

Another way:
In script_that_defines_renderMap.js:
function renderMap(points) {
// take "points" as an argument
}
And then:
<script src="script_that_defines_renderMap.js"/>
<script>
var mapPoints = <?php echo json_encode($this->points); ?>;
renderMap(mapPoints);
</script>
No global variable, no problem.

Related

Dynamically give access to JavaScript functions

The title may be a bit non-descriptive, so let me explain what I want to do.
I have a lot of JavaScript functions that I want to be able to "give access to" based on a user's permissions to do certain things on my system. As an example:
I have a JS function to add an employee:
function doNewEmployee() {
var x;
var objTemp=new Object();
var myElements = new Array ("username","password1", "password2", "emp_type",
"name", "surname", "personal_contact", "work_contact", "location_dd",
"home_address", "access_level", "id_num");
for (x=0;x<myElements.length;x++){
objTemp[''+myElements[x]+'']=document.getElementById(myElements[x]).value;
}
asyncProxy.addNewEmployee(objTemp);
}
This sends all the parameters through AJAX to my PHP
Now, what I want to be able to do is check whether the user has permissions to execute this function and only include it in the final JS file sent client-side if this is true.
Is this possible? I was thinking about just creating a load of if statements, echoing out the javascript functions in the index.php file, but this would entail having all my JS inline, which isn't what I want.
I guess at the end of the day I want a dynamically built JS file?
Any help would be greatly appreciated!

Calling PHP within Javascript results in literal string of function

I feel like i'm going round in circles here and missing something really daft...
My setup is essentially using CodeIgniter on the server-side, and Bootstrap on the client, but that's a little beside the point...
I'm trying to call a php value within a javascript function. The value is being stored in a protected variable within one of the php controllers, which is accessible by the views being loaded in that controller, as i'm accessing the variable directly in the html (and therefore I assumed i could access it in the javascript as well).
The code is here, it's really straight forward:
$(document).ready(function() {
var UID = "<?php echo $the_user->id; ?>";
console.log(UID);
});
I'm expecting this do do a console output of, say, "1", but it's actually outputting the actual string of "<?php echo $the_user->id; ?>". This will also happen if i'm just echoing a simple string, rather than a php variable.
I feel like this might be a config issue, but I really have no idea. If I remove the quotes from the php call, I get a
TypeError: can't wrap XML objects
console.log(<?php echo $the_user->id ?>);
Any ideas? I feel really dumb at this point :(
If you see <?php echo $the_user->id; ?> in the output, it means that your document is not parsed by PHP.
Check the file extension, check that it is indeed send to PHP in your webserver configuration.
For example if you add PHP tags in a .js file, it won't be passed to PHP, if you are using Apache, you would have to add:
AddType application/x-httpd-php .js
or set your variables in the HTML and send it as a parameter to the external Javascript.
mathieu-imbert is right about your file not being processed as a view. That's your first hurdle: make sure the page is being parsed.
Also, when trying to stick PHP variables into javascript, you have to think about escaping variables, dealing with unexpected values, etc.. Fortunately, there is an easy answer:
$(document).ready(function() {
var UID = <?php echo json_encode($the_user->id); ?>;
console.log(UID);
});
You can insert arbitrarily complex data into Javascript this way, provided you mind the usual restrictions with serializing PHP data.

Efficient way to Pass variables from PHP to JavaScript [duplicate]

This question already has answers here:
How do I pass variables and data from PHP to JavaScript?
(19 answers)
Closed 8 years ago.
From time to time I have to pass some variables from PHP to JS script.
For now I did it like this:
var js-variable = "<?php echo $php-variable; ?>";
But this is very ugly and I can't hide my JS script in .js file because it has to be parsed by PHP. What is the best solution to handle this?
If you don't want to use PHP to generate your javascript (and don't mind the extra call to your webserver), use AJAX to fetch the data.
If you do want to use PHP, always encode with json_encode before outputting.
<script>
var myvar = <?php echo json_encode($myVarValue); ?>;
</script>
Please use a rest/rpc api and pass json to your js.
This can be done in the following way if you are using jquery:
rest.php
<?php echo "{name:biplav}" ?>
Then From your js make a get call like this:
var js_var;
$.get("rest.php", function(data) {
js_var=data;
});
Thats the simplest example I can think of.
<?php
// filename: output-json.php
header('content-type:application/json;charset=utf-8');
printf('var foo = %s;', json_encode($foo, JSON_PRETTY_PRINT));
json_encode is a robust function that ensures the output is encoded and formatted as valid javascript / json. The content-type header tells the browser how to interpret the response.
If your response is truly JSON, such as:
{"foo": 5}
Then declare it as content-type:application/json;charset=utf-8. JSON is faster to parse, and has much less chance of being xss exploited when compared to javascript. But, if you need to use real javascript in the response, such as:
var obj = {foo: 5};
Then declare it as content-type:text/javascript;charset=utf-8
You can link to it like a file:
<script src="output-json.php"></script>
Alternatively, it can be convenient to embed the value directly in your html instead of making a separate http request. Do it like so:
<script>
<?php printf('var foo = %s;', json_encode($foo, JSON_HEX_TAG | JSON_PRETTY_PRINT)) ?>
</script>
Make sure to use JSON_HEX_TAG if embedding into your html via the <script> tag, otherwise you risk xss injection attacks. There's also other flags you may need to make use of for more security depending on the context you use it in: JSON_HEX_AMP, JSON_HEX_QUOT, JSON_HEX_APOS. Those flags make the response less human readable, but are generally good for security and compatibility, so you should probably just use them.
I really want to emphasize the importance of declaring the content type and possibly using the JSON_HEX_TAG flag, as they can both help mitigate xss injection.
Do not do this unless you wish to tempt an xss attack:
<script>
var myvar = <?php echo json_encode($myVarValue); ?>;
</script>
In my opinion, if you need to pass a variable directly in your JS, probably your web application is not good designed.
So, I have two tips:
* Use JSON files for general configurations, like /js/conf/userprefs.json
{
"avatar": "/img/users/123/avatar.jpg",
"preferred_color": "blue"
// ...
}
or (better way) you can retrieve your json confs with an AJAX call.
With PHP frameworks like Symfony2, you can decide a format in your routing configuration leaving the output of a variable to the template engine (like Twig).
I do an example for Symfony2 users but this can be used by any programmer:
routing.yml
userprefs:
pattern: /js/confs/userprefs.{_format}
defaults: { _controller: CoreBundle:JsonPrefs:User, _format: json }
requirements:
_format: json
_method: GET
Inside the controller you can do all the queries that you need to retrieve your variables putting these in the view:
Resources/Views/JsonPrefs/User.json
{
"avatar": "{{ user.avatar }}",
"preferred_color": "{{ user.preferred_color }}"
// ...
}
Inside your JS now you'll be able to retrieve the JSON with a simple AJAX call.
For performance purposes you can cache the JSONs (for example) with Varnish. In this way your server doesn't need to do a query every time you read the user preferences.
If you modify your .htaccess file to include
AddType application/x-httpd-php .js
you can use a .js file and it will be handled by PHP, which is half of what you require.
In terms of how ugly that solution is, I would say that this is the least ugly mechanism. You could try to pass your whole JS script through a PHP script as a string and do a search and replace for the variables you need to insert, but I think that you will agree that this is uglier than the solution you are currently using.
Put all your .js files in a folder and configure your HTTP server to redirect all the request to those files to a PHP file that loads the files and outputs them.
Let's suppose you have Apache and your .js files are in /js:
RewriteRule /js /getjs.php
getjs.php:
<?php
header('Content-Type: text/javascript');
include_once($_SERVER['SCRIPT_NAME']);
?>
As far as avoiding running .js files through the PHP parser, there is little you can do, except maybe fetching the value of js-variable via an AJAX call.
Also you may consider outputing the value like this:
var js_variable = <?php echo json_encode ($php_variable); ?>
to escape all the things that would break your javascript.
At the very least, you can use a PHP shortcode to make your "ugly" solution a bit cleaner:
var js-variable = "<?= $php-variable ?>";

Most efficient way to make ajax request for a particular element

I have been playing with jQuery .load function to grab a particular div from a page.
$('#result').load('ajax/test.html #variable123');
This works like it should, however it is taking forever because the Response still contains the complete document even though all that is returned in #result is the div that I defined.. in this example #variable123
Is there another way I could accomplish this but only have the response contain that actual div? What would be the fastest way to return this result?
To further clarify, the id that I am searching for is generated from a foreach loop on each page.
<img name="<?php echo $_product->getId() ?>"
and then an onclick event for them to make the ajax request for that related div id.
$('img').click(function () {
$('#result').load('ajax/test.html .' + $(this).attr("name"));
});
The page test.html also has a foreach loop that generates div blocks with the same id as was passed in the name. David and Juan both suggested sever side solutions. Can someone please explain this a bit more to me?
Since you can't fetch arbitrary parts of a file:
$('#result').load('ajax/test_with_only_variable123_in_it.html');
You can, of course, use a server side program instead of generating a bundle of static files.
As others suggested, you need to implement the functionality server side, not client side. It is not possible to use javascript to load part of a html file, so you'll either need to have an individual html file for every result you'll require (as David suggested), or create a server side script to manage this for you. For example:
Your html/js file would look like this:
$('img').click(function () {
$('#result').load('ajax/test.php?id=' + $(this).attr('name'));
});
I would probably use .get() or .ajax() over .load() to pass the data, but for this example, .load() should work as above.
In your test.php file, get the ID, and load the required content (something like this):
<?php
// load class/model/whatever you need to do
$id = $_GET['id'];
$product = $productmodel->get($id); // or however you load a single product from your class/model
// echo data from $product
?>
If the second part doesn't make sense, please let us know how your products are stored ( whether you're using a simple OO approach, or using a php framework such as codeigniter) and we'll try to give a more detailed example of the server side code.
you could try to call to a function like this:
$('#target').load("functions.php",{action:"that_div"});
if($_POST){
$action = $_POST['action'];
if($action == "that_div"){
exit( "<div>Your div</div>" );
}
if($action == "another_div"){
exit("<div>Your another div</div>");
}
}
as David sugested

AJAX calling a PHP code and getting a response every few minutes

I'm trying to create a very simple message board (author, text, and date written) that will auto-update every few moments to see if a new message has arrived, and if it has, auto load the latest message(s).
I'm proficient in PHP, but my knowledge in AJAX is lacking.
The way I see it, I would have to create a PHP file called get_messages.php that would connect to a database and get through a $_GET variable return all posts beyond date X, and then I would somehow through jquery call this PHP file every few minutes with $_GET=current time?
Does this sound correct?
How would I got about requesting and returning the data to the web page asynchronously?
You're pretty close, you'll need a PHP script that can query the database for your results. Next, you'll want to transfigure those results into an array, and json_encode() them:
$results = getMyResults();
/* Assume this produce the following Array:
Array(
"id" => "128","authorid" => "12","posttime" => "12:53pm",
"comment" => "I completely agree! Stackoverflow FTW!"
);
*/
print json_encode($results);
/* We'll end up with the following JSON:
{
{"id":"128"},{"authorid":"12"},{"posttime":"12:53pm"},
{"comment":"I completely agree! Stackoverflow FTW!"}
}
*/
Once these results are in JSON format, you can better handle them with javascript. Using jQuery's ajax functionality, we can do the following:
setInterval("update()", 10000); /* Call server every 10 seconds */
function update() {
$.get("serverScript.php", {}, function (response) {
/* 'response' is our JSON */
alert(response.comment);
}, "json");
}
Now that you've got your data within javascript ('response'), you are free to use the information from the server.
Ignore the ASP.NET stuff, this link is a good start:
http://www.aspcode.net/Timed-Ajax-calls-with-JQuery-and-ASPNET.aspx
What you're going to use is a javascript function called setTimeout, which asynchronously calls a javascript function on an interval. From there, jQuery has a fancy function called "load" that will load the results of an AJAX call into a DIV or whatever element you're looking for. There are also numerous other ways to get jQuery to do alter the DOM the way you'd like.
There are a hundred ways to do this, but I'd say avoid writing plain Javascript to save yourself the headache of cross-browser functionality when you can.
I suggest you go for the Simple AJAX Code-Kit (SACK) available on Google code.
I've been using it since before it was on Google code. It's very light and straightforward. It's one js file that you have to include. I've seen it being used in online browser games as well.
http://code.google.com/p/tw-sack/
Example for loading page contents from get_messages.php in a div (if you don't care about the page contents from get_messages.php, and simply want to call the php file, simple remove the ajax.element line):
<script type="text/javascript" src="tw-sack.js"></script>
<script>
var ajax = new sack();
ajax.method = "GET"; // Can also be set to POST
ajax.element = 'my_messages'; // Remove to make a simple "ping" type of request
ajax.requestFile = "get_messages.php";
ajax.setVar("user_name","bobby");
ajax.setVar("other_variables","hello world");
ajax.setVar("time",dateObject.getTime());
ajax.onCompleted = whenCompleted;
ajax.runAJAX();
function whenCompleted(){
alert('completed');
}
</script>
<div id="my_messages">Loading...</div>
You don't need to specify an "ajax.element" if you want to do a simple "ping" type of request and ignore the output of the php file. All you have to do to implement your requirements now is to use a "setTimeout" making the ajax calls.
There are also many other options like:
//ajax.onLoading = whenLoading;
//ajax.onLoaded = whenLoaded;
//ajax.onInteractive = whenInteractive;
No need to learn or include huge frameworks. And you'll get started in no time with tw-sack.

Categories