PDA

View Full Version : Using a .php script in javascript



CoderInTraining
Feb 12th, 2011, 09:12 PM
Hi,
I was wondering how to load an external .php script file in javascript, and make use of a php variable in the javascript.

Thanks in advance.

EDIT: If this is not possible, is there some way to send the php data to the javascript by using php, and then accessing the data that was sent in the javascript, and making use of it? What I'm trying to do is get a OpenTok session id from a .php script to javascript.

Old Pedant
Feb 12th, 2011, 10:42 PM
You could use AJAX to get information from PHP into JavaScript while a page is running.

But it sounds to me like all you need is what you asked for secondarily.

And then it's trivial:


...
<script type="text/javascript">

var openTokSession = "<?php echo $session["whatever"]; ?>";

... other js code ...

</script>
...

You see it? You can dump any amount of PHP info into your JS variables in this way. You can drop entire arrays of information, if you do it right.

NOTE: If you enable PHP "short tags" (I think that's what they are called...I'm not a PHP person) you can write it even more compactly:


var openTokSession = "<?= $session["whatever"] ?>";

That's what I'd do if I used PHP.

venegal
Feb 12th, 2011, 11:19 PM
The use of shorttags is discouraged because of portability considerations and potential problems with XML declarations.

Also, doing it like that

var openTokSession = "<?php echo $session["whatever"]; ?>";

is problematic, because there could be double quotes inside the string which would break the script.

The recommended way is this

var openTokSession = <?php echo json_encode($session['whatever']); ?>;

which doesn't have that problem and will also work if $session['whatever'] is something other than a string.

CoderInTraining
Feb 12th, 2011, 11:23 PM
You could use AJAX to get information from PHP into JavaScript while a page is running.

But it sounds to me like all you need is what you asked for secondarily.

And then it's trivial:


...
<script type="text/javascript">

var openTokSession = "<?php echo $session["whatever"]; ?>";

... other js code ...

</script>
...

You see it? You can dump any amount of PHP info into your JS variables in this way. You can drop entire arrays of information, if you do it right.

NOTE: If you enable PHP "short tags" (I think that's what they are called...I'm not a PHP person) you can write it even more compactly:


var openTokSession = "<?= $session["whatever"] ?>";

That's what I'd do if I used PHP.
But would that even work, if the php data I need is in an external .php script? I would think I would have to load the .php file first, probably using Ajax like you said. However, I don't know how to do that.

The PHP file contains this:



<?php

require_once 'SDK/API_Config.php';

require_once 'SDK/OpenTokSDK.php';

require_once 'SDK/SessionPropertyConstants.php';


$apiObj = new OpenTokSDK(API_Config::API_KEY, API_Config::API_SECRET);



$session = $apiObj->create_session($_SERVER["REMOTE_ADDR"],

array(SessionPropertyConstants::MULTIPLEXER_NUMOUTPUTSTREAMS=>2,

SessionPropertyConstants::ECHOSUPPRESSION_ENABLED=>"true",

SessionPropertyConstants::MULTIPLEXER_SWITCHTYPE=>1,

SessionPropertyConstants::MULTIPLEXER_SWITCHTIMEOUT=>5000));



$session_id = $session->getSessionId();

?>


I need to get the $session_id into a Javascript. The $session_id will contain a different value each time the .php script runs.

EDIT: Nevermind...duh. All I need to do is copy the php code into a javascript string variable, and forget about the external script.

CoderInTraining
Feb 13th, 2011, 12:56 AM
The use of shorttags is discouraged because of portability considerations and potential problems with XML declarations.

Also, doing it like that

var openTokSession = "<?php echo $session["whatever"]; ?>";

is problematic, because there could be double quotes inside the string which would break the script.

The recommended way is this

var openTokSession = <?php echo json_encode($session['whatever']); ?>;

which doesn't have that problem and will also work if $session['whatever'] is something other than a string.
Does this method work if the php statements are on multiple lines?

venegal
Feb 13th, 2011, 01:05 AM
Why would there be multiple lines? It's just a variable. How many lines it takes you to get the desired value into that variable is irrelevant (and should be done somewhere else anyway). If you need an external PHP script to set the PHP variable before defining it as a Javascript variable, you just include that script. You definitely don't want to put a long PHP script into the Javascript variable definition that would be a readability nightmare (not to mention the obvious violation of the separation of concerns principle).

CoderInTraining
Feb 13th, 2011, 01:14 AM
Why would there be multiple lines? It's just a variable. How many lines it takes you to get the desired value into that variable is irrelevant (and should be done somewhere else anyway). If you need an external PHP script to set the PHP variable before defining it as a Javascript variable, you just include that script. You definitely don't want to put a long PHP script into the Javascript variable definition — that would be a readability nightmare (not to mention the obvious violation of the separation of concerns principle).
Well, I was going to try something like this in my Javascript:



var session_id = <?php

require_once 'SDK/API_Config.php';

require_once 'SDK/OpenTokSDK.php';

require_once 'SDK/SessionPropertyConstants.php';


$apiObj = new OpenTokSDK(API_Config::API_KEY, API_Config::API_SECRET);



$session = $apiObj->create_session($_SERVER["REMOTE_ADDR"],

array(SessionPropertyConstants::MULTIPLEXER_NUMOUTPUTSTREAMS=>2,

SessionPropertyConstants::ECHOSUPPRESSION_ENABLED=>"true",

SessionPropertyConstants::MULTIPLEXER_SWITCHTYPE=>1,

SessionPropertyConstants::MULTIPLEXER_SWITCHTIMEOUT=>5000));



$session_id = $session->getSessionId();
echo $session_id;

?>;

But you're right. I should give $session_id its value in the external create_session.php file, and then just echo the $session_id in the javascript variable definition. But I still have the problem of loading the .php external script through Javascript or AJAX. I still don't know how to do that.

Thanks.

CoderInTraining
Feb 13th, 2011, 05:33 PM
Hmm...it looks this should work:



if (window.XMLHttpRequest) // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();

else // code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
var session_id = xmlhttp.responseText;
}
xmlhttp.open("GET","URL_OMITTED/create_session.php");
xmlhttp.send();

Let me know if you have any better ideas.

CoderInTraining
Feb 24th, 2011, 12:38 AM
Ok, the XMLHttpRequest approach worked to an extent, but I didn't like the fact that it didn't wait until the var session_id was initialized by the server response before executing the rest of the script. To get around it, I set var session_id to null before the onreadystatechange function definition, and then inside the function set session_id to xmlhttp.responseText, and then after the request is sent, I put a while (session_id == null) loop to wait until session_id was set, so that I could then use the session_id (instead of letting it use it while its still null). But my browser displayed an alert saying my script was either busy or was not responding, and asked if I wanted to continue or ignore the script. And since I don't want to give the user that option, I had to think of a different approach.

Thus, I commented out the whole XMLHttpRequest stuff in my code, and changed the create_session.php script to the following:



<?php
header("Access-Control-Allow-Origin: *");
require_once 'API_Config.php';
require_once 'OpenTokSDK.php';
require_once 'SessionPropertyConstants.php';

$session_id = $session->getSessionId();
function getSessionId() {
$apiObj = new OpenTokSDK(API_Config::API_KEY, API_Config::API_SECRET);

$session = $apiObj->create_session($_SERVER["REMOTE_ADDR"],
array(SessionPropertyConstants::MULTIPLEXER_NUMOUTPUTSTREAMS=>2,
SessionPropertyConstants::ECHOSUPPRESSION_ENABLED=>"true",
SessionPropertyConstants::MULTIPLEXER_SWITCHTYPE=>1,
SessionPropertyConstants::MULTIPLEXER_SWITCHTIMEOUT=>5000));
$session_id = $session->getSessionId();
return $session_id;
}
echo getSessionId();
?>

And then I wrote this in the javascript to obtain the session_id and api_key:



var session_id = <?php echo json_encode(getSessionId();); ?>;
alert("session_id is: " + session_id);
var api_key = <?php echo json_encode(API_Config::API_KEY); ?>;
alert("api_key is: " + api_key);

But the alerts reveal both of them are empty, and don't contain anything.
Am I wrong to think that PHP variables and functions can be accessed directly anywhere on the same server?

venegal
Feb 24th, 2011, 09:47 AM
Ok, the XMLHttpRequest approach worked to an extent, but I didn't like the fact that it didn't wait until the var session_id was initialized by the server response before executing the rest of the script. To get around it, I set var session_id to null before the onreadystatechange function definition, and then inside the function set session_id to xmlhttp.responseText, and then after the request is sent, I put a while (session_id == null) loop to wait until session_id was set, so that I could then use the session_id (instead of letting it use it while its still null). But my browser displayed an alert saying my script was either busy or was not responding, and asked if I wanted to continue or ignore the script. And since I don't want to give the user that option, I had to think of a different approach.


This is very wrong. You are setting that variable in the onreadystatechange handler, which means that this should happen once the AJAX call comes back with a response, and thus the onreadystatechange event fires. The thing is, though, that event handlers won't be executed before the script has become idle (has nothing else to do). But that while loop will make sure that it never runs out of things to do it will loop and loop and loop and never rest, and for that it will use all the available CPU, which is why the browser gives you the option to stop script execution, because obviously something went wrong and will freeze your whole computer if not stopped.

I understand what you tried to do periodically check if the value is there already. For some reason, beginners like to do that, and it can be accomplished using setTimeout or setInterval. That way the script becomes idle between intervals and the event handler can run.

That's still wrong though. You already have a perfectly good AJAX callback in place (the onreadystatechange handler, where you set the session_id variable (which you're doing wrong, btw, because in your code it will be a local variable that can't be accessed from anywhere else)). Just put the stuff you want to do once the AJAX has come back into that callback. That's what it's there for.


Am I wrong to think that PHP variables and functions can be accessed directly anywhere on the same server?


Your PHP will simply run from top to bottom, and if you haven't included/required the files where those variables and functions are actually defined, you can't use them.

Kor
Feb 24th, 2011, 10:58 AM
but I didn't like the fact that it didn't wait until the var session_id was initialized by the server response before executing the rest of the script
It depends on what you understand by "the rest of the code".

It looks like you miss the essential characteristic of an AJAX request. As long the the 3-rd argument of the method open() (by the way, you omitted it) is a Boolean true, the request works asynchronously. As the acronym says: (Asynchronous JavaScript And XML)\

If you need something to work synchronous with the request, either you make the request synchronous (by using the Boolean false within the open()), or you write "that rest of the code" inside the onreadystatechange handler.

CoderInTraining
Feb 24th, 2011, 06:22 PM
This is very wrong. You are setting that variable in the onreadystatechange handler, which means that this should happen once the AJAX call comes back with a response, and thus the onreadystatechange event fires. The thing is, though, that event handlers won't be executed before the script has become idle (has nothing else to do). But that while loop will make sure that it never runs out of things to do — it will loop and loop and loop and never rest, and for that it will use all the available CPU, which is why the browser gives you the option to stop script execution, because obviously something went wrong and will freeze your whole computer if not stopped.

Oh...ok. I didn't know that. I just assumed the event handler would be called whenever the event actually took place, and not after the script has been idle.


I understand what you tried to do — periodically check if the value is there already. For some reason, beginners like to do that, and it can be accomplished using setTimeout or setInterval. That way the script becomes idle between intervals and the event handler can run.

That's still wrong though. You already have a perfectly good AJAX callback in place (the onreadystatechange handler, where you set the session_id variable (which you're doing wrong, btw, because in your code it will be a local variable that can't be accessed from anywhere else)). Just put the stuff you want to do once the AJAX has come back into that callback. That's what it's there for.

Hmm...good idea. I didn't think of that.
But what did you mean by "its wrong, because in your code it will be a local variable that can't be accessed from anywhere else"? Why would it NEED to be accessed anywhere else? I do all the stuff with the session_id variable in one single javascript.



Your PHP will simply run from top to bottom, and if you haven't included/required the files where those variables and functions are actually defined, you can't use them.
And by that, you're talking about the actual external .php file that I uploaded to the same server as the Javascript, right? Not the php inside the Javascript? So in other words, I need to load the PHP file using an XMLHttpRequest first, before I can use anything defined inside said PHP file, instead of trying to the PHP function directly from inside the Javascript, like I was trying to do? Ok, got it...

Thanks much. :thumbsup:

EDIT: Ok, did that, but seriously need another approach. I'm in my Ubuntu OS right now, and my browser (Firefox) appears to be blocking the XMLHttpRequest. My Error Console says:



Security error: Content at URL_OMITTED may not load data from URL_OMITTED/create_session.php.
Error: uncaught exception: [Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" location: "URL_OMITTED Line: 1218"]


Line: 1218 is the line of my Javascript that looks like this:



xmlhttp.open("GET","URL_OMITTED/create_session.php", true);


so in other words, its where I attempt to "open" the create_session.php file with an XMLHttpRequest object called "xmlhttp".
I was having this problem before, that's why I changed the code to try to use the Javascript appoach above which attempts to directly call the .php function getSessionId(). But since that obviously wont work, anyone got a better approach?
Side note: The XMLHttpRequest seems to work just fine from my other OS (XP; I have a multiboot), but it doesn't work in Ubuntu for some reason.

CoderInTraining
Feb 24th, 2011, 06:24 PM
It depends on what you understand by "the rest of the code".

It looks like you miss the essential characteristic of an AJAX request. As long the the 3-rd argument of the method open() (by the way, you omitted it) is a Boolean true, the request works asynchronously. As the acronym says: (Asynchronous JavaScript And XML)\

If you need something to work synchronous with the request, either you make the request synchronous (by using the Boolean false within the open()), or you write "that rest of the code" inside the onreadystatechange handler.
Well, I already tried passing false to the open function, but session_id was still empty when it got passed to the OpenTok Javascript API, until I put the while loop in. But since you both kind of indicated that doing so is bad form, I'll try doing what Venegal suggested above.

Btw, I did not omit the 3rd argument of open when I actually made the request. I just omitted it in the above post, because I did not see a real need for it, because the default value is true, and I wanted to pass true there. But I did end up putting it in my actual code, anyway, and attempted to use false a couple of times, but session_id was still empty after the request was sent, and I alerted the value of session_id.

Cheers..

Thanks. :D

venegal
Feb 24th, 2011, 06:55 PM
But what did you mean by "its wrong, because in your code it will be a local variable that can't be accessed from anywhere else"? Why would it NEED to be accessed anywhere else? I do all the stuff with the session_id variable in one single javascript.


I'm talking about this snippet here:

xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
var session_id = xmlhttp.responseText;
}


You're defining session_id inside the AJAX callback, so it won't be available anywhere else (meaning anywhere outside of that callback). Since you're not doing anything else in the callback than setting that variable (yet), that's an obvious mistake. No matter what you do elsewhere in the script, deleting that variable definition won't make any difference, because the variable is invisible to all other parts of your script anyway.



And by that, you're talking about the actual external .php file that I uploaded to the same server as the Javascript, right? Not the php inside the Javascript? So in other words, I need to load the PHP file using an XMLHttpRequest first, before I can use anything defined inside said PHP file, instead of trying to the PHP function directly from inside the Javascript, like I was trying to do? Ok, got it...


I'm not quite sure you got it, because it sounds kind of confused what you're saying there, mixing Javascript and PHP in your sentences like that. This doesn't have anything to do with Javascript at all. The server gets a request for a PHP file (no matter if that request is started by typing an address into the URL bar of your browser, or by AJAX). It then opens that PHP file and reads one line after the other. If there's an include/require, it opens that file, and reads that one line after the other until the end, before returning to the original one. That's the basic flow I'm talking about, and all I'm saying is that if you want to access some PHP variable or function at some point in your PHP script, that's only possible if it has already been defined somewhere earlier in that flow.

Whatever Javascript you got in there is irrelevant for PHP that's just text. It's only once PHP has completely finished its job and the page is sent to the browser that that becomes interesting.

In this snippet here

var session_id = <?php echo json_encode(getSessionId();); ?>;
alert("session_id is: " + session_id);
if the alert doesn't show you an actual session_id, that just means that PHP hasn't put one there in the first place (long before the site ever reached the browser and the Javascript became actual code, as opposed to irrelevant gibberish), so it's a PHP error with a really silly method of debugging it using Javascript. You should forget your Javascript completely and track down in your PHP code why
echo json_encode(getSessionId();); doesn't output anything. (One reason it fails is that superflous semicolon inside the json_encode call.)

CoderInTraining
Feb 24th, 2011, 07:14 PM
I'm talking about this snippet here:

xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200)
var session_id = xmlhttp.responseText;
}


You're defining session_id inside the AJAX callback, so it won't be available anywhere else (meaning anywhere outside of that callback). Since you're not doing anything else in the callback than setting that variable (yet), that's an obvious mistake. No matter what you do elsewhere in the script, deleting that variable definition won't make any difference, because the variable is invisible to all other parts of your script anyway.

Oh, right. Yeah, I don't actually have that in that function anymore. The XMLHttpRequest code above is a little outdated. I changed a few things, since writing that. Now I define session_id outside of the function, before the function definition, and then I just initialize the session_id variable inside the function.

Here is my current XMLHttpRequest code:



if (window.XMLHttpRequest) // code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();

else // code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

xmlhttp.open("GET","http://URL_OMITTED/create_session.php", true);

var session_id = null;
function getSessionID() {

if (xmlhttp.readyState==4 && xmlhttp.status==200) {
session_id = xmlhttp.responseText;
alert("session_id is: " + session_id);
}

}

xmlhttp.onreadystatechange = getSessionID;
xmlhttp.send();



I'm not quite sure you got it, because it sounds kind of confused what you're saying there, mixing Javascript and PHP in your sentences like that. This doesn't have anything to do with Javascript at all. The server gets a request for a PHP file (no matter if that request is started by typing an address into the URL bar of your browser, or by AJAX). It then opens that PHP file and reads one line after the other. If there's an include/require, it opens that file, and reads that one line after the other until the end, before returning to the original one. That's the basic flow I'm talking about, and all I'm saying is that if you want to access some PHP variable or function at some point in your PHP script, that's only possible if it has already been defined somewhere earlier in that flow.

Yes, but I was talking about accessing a PHP variable or function in a Javascript, through the:



var session_id = <?php echo getSessionId(); ?>;

syntax, because I was asking if that was possible or not. The reason I had thought it might be was because I read something online that said a .php variable name can be used anywhere from any php script, or something to that effect, so I was wondering if it extended to functions as well, which is what sparked attempting the above code line (which didn't work).


Whatever Javascript you got in there is irrelevant — for PHP that's just text. It's only once PHP has completely finished its job and the page is sent to the browser that that becomes interesting.

In this snippet here

var session_id = <?php echo json_encode(getSessionId();); ?>;
alert("session_id is: " + session_id);
if the alert doesn't show you an actual session_id, that just means that PHP hasn't put one there in the first place (long before the site ever reached the browser and the Javascript became actual code, as opposed to irrelevant gibberish), so it's a PHP error with a really silly method of debugging it using Javascript. You should forget your Javascript completely and track down in your PHP code why
echo json_encode(getSessionId();); doesn't output anything. (One reason it fails is that superflous semicolon inside the json_encode call.)
Oh...so you're saying that that does work (if you do it right)? So I just need to remove the semicolon, I guess then. I am certain the .php script is correct, but just to prove it, here is the contents of create_session.php which contains the getSessionId() function:



<?php
header("Access-Control-Allow-Origin: *");
require_once 'API_Config.php';
require_once 'OpenTokSDK.php';
require_once 'SessionPropertyConstants.php';

$session_id = $session->getSessionId();
function getSessionId() {
$apiObj = new OpenTokSDK(API_Config::API_KEY, API_Config::API_SECRET);

$session = $apiObj->create_session($_SERVER["REMOTE_ADDR"],
array(SessionPropertyConstants::MULTIPLEXER_NUMOUTPUTSTREAMS=>2,
SessionPropertyConstants::ECHOSUPPRESSION_ENABLED=>"true",
SessionPropertyConstants::MULTIPLEXER_SWITCHTYPE=>1,
SessionPropertyConstants::MULTIPLEXER_SWITCHTIMEOUT=>5000));
$session_id = $session->getSessionId();
return $session_id;
}
echo getSessionId();
?>


EDIT: Oops..there was something wrong in the .php script. I forgot to remove that line before function defintion of getSessionId(). My bad...