Is there a way I can run a php function through a JS function?
something like this:
<script type="text/javascript">
function test(){
document.getElementById("php_code").innerHTML="<?php
query("hello"); ?>";
}
</script>
<a href="#" style="display:block; color:#000033; font-family:Tahoma; font-size:12px;"
onclick="test(); return false;"> test </a>
<span id="php_code"> </span>
I basically want to run the php function query("hello"), when I click on the href called "Test" which would call the php function.
This is, in essence, what AJAX is for. Your page loads, and you add an event to an element. When the user causes the event to be triggered, say by clicking something, your Javascript uses the XMLHttpRequest object to send a request to a server.
After the server responds (presumably with output), another Javascript function/event gives you a place to work with that output, including simply sticking it into the page like any other piece of HTML.
You can do it "by hand" with plain Javascript , or you can use jQuery. Depending on the size of your project and particular situation, it may be more simple to just use plain Javascript .
Plain Javascript
In this very basic example, we send a request to myAjax.php when the user clicks a link. The server will generate some content, in this case "hello world!". We will put into the HTML element with the id output.
The javascript
// handles the click event for link 1, sends the query
function getOutput() {
getRequest(
'myAjax.php', // URL for the PHP file
drawOutput, // handle successful request
drawError // handle error
);
return false;
}
// handles drawing an error message
function drawError() {
var container = document.getElementById('output');
container.innerHTML = 'Bummer: there was an error!';
}
// handles the response, adds the html
function drawOutput(responseText) {
var container = document.getElementById('output');
container.innerHTML = responseText;
}
// helper function for cross-browser request object
function getRequest(url, success, error) {
var req = false;
try{
// most browsers
req = new XMLHttpRequest();
} catch (e){
// IE
try{
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch(e) {
// try an older version
try{
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
return false;
}
}
}
if (!req) return false;
if (typeof success != 'function') success = function () {};
if (typeof error!= 'function') error = function () {};
req.onreadystatechange = function(){
if(req.readyState == 4) {
return req.status === 200 ?
success(req.responseText) : error(req.status);
}
}
req.open("GET", url, true);
req.send(null);
return req;
}
The HTML
test
<div id="output">waiting for action</div>
The PHP
// file myAjax.php
<?php
echo 'hello world!';
?>
Try it out: http://jsfiddle.net/GRMule/m8CTk/
With a javascript library (jQuery et al)
Arguably, that is a lot of Javascript code. You can shorten that up by tightening the blocks or using more terse logic operators, of course, but there's still a lot going on there. If you plan on doing a lot of this type of thing on your project, you might be better off with a javascript library.
Using the same HTML and PHP from above, this is your entire script (with jQuery included on the page). I've tightened up the code a little to be more consistent with jQuery's general style, but you get the idea:
// handles the click event, sends the query
function getOutput() {
$.ajax({
url:'myAjax.php',
complete: function (response) {
$('#output').html(response.responseText);
},
error: function () {
$('#output').html('Bummer: there was an error!');
}
});
return false;
}
Try it out: http://jsfiddle.net/GRMule/WQXXT/
Don't rush out for jQuery just yet: adding any library is still adding hundreds or thousands of lines of code to your project just as surely as if you had written them. Inside the jQuery library file, you'll find similar code to that in the first example, plus a whole lot more. That may be a good thing, it may not. Plan, and consider your project's current size and future possibility for expansion and the target environment or platform.
If this is all you need to do, write the plain javascript once and you're done.
Documentation
AJAX on MDN - https://developer.mozilla.org/en/ajax
XMLHttpRequest on MDN - https://developer.mozilla.org/en/XMLHttpRequest
XMLHttpRequest on MSDN - http://msdn.microsoft.com/en-us/library/ie/ms535874%28v=vs.85%29.aspx
jQuery - http://jquery.com/download/
jQuery.ajax - http://api.jquery.com/jQuery.ajax/
PHP is evaluated at the server; javascript is evaluated at the client/browser, thus you can't call a PHP function from javascript directly. But you can issue an HTTP request to the server that will activate a PHP function, with AJAX.
The only way to execute PHP from JS is AJAX.
You can send data to server (for eg, GET /ajax.php?do=someFunction)
then in ajax.php you write:
function someFunction() {
echo 'Answer';
}
if ($_GET['do'] === "someFunction") {
someFunction();
}
and then, catch the answer with JS (i'm using jQuery for making AJAX requests)
Probably you'll need some format of answer. See JSON or XML, but JSON is easy to use with JavaScript. In PHP you can use function json_encode($array); which gets array as argument.
I recently published a jQuery plugin which allows you to make PHP function calls in various ways: https://github.com/Xaxis/jquery.php
Simple example usage:
// Both .end() and .data() return data to variables
var strLenA = P.strlen('some string').end();
var strLenB = P.strlen('another string').end();
var totalStrLen = strLenA + strLenB;
console.log( totalStrLen ); // 25
// .data Returns data in an array
var data1 = P.crypt("Some Crypt String").data();
console.log( data1 ); // ["$1$Tk1b01rk$shTKSqDslatUSRV3WdlnI/"]
I have a way to make a Javascript call to a PHP function written on the page (client-side script). The PHP part 'to be executed' only occurs on the server-side on load or refreshing'. You avoid 'some' server-side resources. So, manipulating the DOM:
<?PHP
echo "You have executed the PHP function 'after loading o refreshing the page<br>";
echo "<i><br>The server programmatically, after accessing the command line resources on the server-side, copied the 'Old Content' from the 'text.txt' file and then changed 'Old Content' to 'New Content'. Finally sent the data to the browser.<br><br>But If you execute the PHP function n times your page always displays 'Old Content' n times, even though the file content is always 'New Content', which is demonstrated (proof 1) by running the 'cat texto.txt' command in your shell. Displaying this text on the client side proves (proof 2) that the browser executed the PHP function 'overflying' the PHP server-side instructions, and this is because the browser engine has restricted, unobtrusively, the execution of scripts on the client-side command line.<br><br>So, the server responds only by loading or refreshing the page, and after an Ajax call function or a PHP call via an HTML form. The rest happens on the client-side, presumably through some form of 'RAM-caching</i>'.<br><br>";
function myPhp(){
echo"The page says: Hello world!<br>";
echo "The page says that the Server '<b>said</b>': <br>1. ";
echo exec('echo $(cat texto.txt);echo "Hello world! (New content)" > texto.txt');echo "<br>";
echo "2. I have changed 'Old content' to '";
echo exec('echo $(cat texto.txt)');echo ".<br><br>";
echo "Proofs 1 and 2 say that if you want to make a new request to the server, you can do: 1. reload the page, 2. refresh the page, 3. make a call through an HTML form and PHP code, or 4. do a call through Ajax.<br><br>";
}
?>
<div id="mainx"></div>
<script>
function callPhp(){
var tagDiv1 = document.createElement("div");
tagDiv1.id = 'contentx';
tagDiv1.innerHTML = "<?php myPhp(); ?>";
document.getElementById("mainx").appendChild(tagDiv1);
}
</script>
<input type="button" value="CallPHP" onclick="callPhp()">
Note: The texto.txt file has the content 'Hello world! (Old content).
The 'fact' is that whenever I click the 'CallPhp' button I get the message 'Hello world!' printed on my page. Therefore, a server-side script is not always required to execute a PHP function via Javascript.
But the execution of the bash commands only happens while the page is loading or refreshing, never because of that kind of Javascript apparent-call raised before. Once the page is loaded, the execution of bash scripts requires a true-call (PHP, Ajax) to a server-side PHP resource.
So, If you don't want the user to know what commands are running on the server:
You 'should' use the execution of the commands indirectly through a PHP script on the server-side (PHP-form, or Ajax on the client-side).
Otherwise:
If the output of commands on the server-side is not delayed:
You 'can' use the execution of the commands directly from the page (less 'cognitive' resources—less PHP and more Bash—and less code, less time, usually easier, and more comfortable if you know the bash language).
Otherwise:
You 'must' use Ajax.
Related
I have a PHP file that does data processing. It's run by $.ajax(), sometimes on big files that take a long time to process. I need to log some info about the ongoing process in the browser console that is displayed on the go, not just when the PHP file has finished running.
From the research I did, I get that there are two difficulties:
Getting PHP to spit out something before it's done
Getting jQuery/JS to display it on the go
To address #1, I've tried:
echo "started"."<br>";
foreach (array("done this", "done that","had a coffee","burp") as $msg) {
sleep(3);
echo $msg."<br>";
flush();
ob_flush();
}
flush(); ob_flush(); is supposed to do the job, although as you can test here it does not strictly display ever 3s as it's expected to. Any suggestion to get it to display as expected?
As for how to address #2, I have explored a solution involving XMLHttpRequest, but I'm not familiar with the subject so not sure neither what to look for nor if it's the right direction...
Here is the test code of what I'm trying to get to run:
$("#run").click(function(e) {
$.ajax({
url: "http://constances-web-dev.vjf.inserm.fr/constances-web/ajax-test.php",
xhr: function() {
// get the native XmlHttpRequest object
var xhr = $.ajaxSettings.xhr();
xhr.addEventListener('readystatechange', function(e) {
console.log(e)
});
// set the onprogress event handler
//xhr.onprogress = function(evt){ console.log(evt.target.response) } ;
// set the onload event handler
return xhr;
},
success: function(msg) {
console.log(msg);
},
error: function(msg) {
console.log("Erreur: " + msg);
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="run">go</button>
Subsidiary question: Is there an (easy) way to go around the cross-origin restriction in order to get an AJAX example to work in a SO snippet?
as a work around I've added a log to file to my write2log function
static function log2File($string, $logFileName) {
if (substr($string,0,1 ) == "\n")
exec("echo '".date('Y-m-d_H:i:s')." ".addslashes(substr($string,1))."' >> ".$logFileName,$output,$status);
else
exec("echo -n ".addslashes($string)."' >> ".$logFileName,$output,$status);
}
I can then tail -f the log to watch how things are going
but this takes ssh access to the server so
i'd still be interested in figuring out how to log to console
What exactly is the magic that jQuery does that causes execution of JS code inside script tags found inside an AJAX response?
For example, when not using jQuery AJAX like below, I see use of eval() is frequently described as as a way to do this:
Calling a JavaScript function returned from an Ajax response
Can scripts be inserted with innerHTML?
So eval does the magic of code execution in those cases. I do not see the use of eval in jQuery AJAX calls.
jQuery Magic
$("#form").submit(function() {
$.ajax({
type : "POST",
url : 'process_form.php',
data : $("#form").serialize(),
success : function(data) {
$("#main_page").load('main_page.php');
}
});
return false;
});
Here jQuery sets up an event (form submit) to where clicking submit on a form submits the form and then it AJAX-loads the DIV with information returned from main_page.php (That page contains update information + JS + jQuery) into main_page div element. But, not just that.
It also triggers and runs and executes any JS/jQuery code located inside the script tags of the ajax-loaded data without any use of eval that I can see
Question: How does it do that?
Note:
I am using some 3rd party proprietary AJAX library, which properly loads up the response into main_page div but then it does not run any JS/jQuery.
Note 2:
to be clear, there is no problem at all with the jQuery code in question. It works and executes whatever JS was in the main_page.php. The proprietary AJAX library that I use loads up the page but does not execute any AJAX in it. I want to figure out what makes it not execute the code when jQuery executes the code.
3rd Paty Library that does not trigger script tag code execution
Delving into the library I see this:
http_req.open(method, url, true);
if (method == "POST") {
http_req.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
http_req.setRequestHeader("Content-length", post_str.length);
http_req.setRequestHeader("Connection", "close");
http_req.send(post_str);
} else if (method == "GET") {
http_req.send(null);
}
Library is called using something like this event on a submit button:
onclick="process_form(..., url, 'main_page'...)"
It also has this:
var responseObj = new getObject(response);
responseObj.obj.innerHTML = http_req.responseText;
Full code surrounding the above:
http_req.onreadystatechange = function() {
if (http_req.readyState == 4 || http_req.readyState == "complete") {
if (response != "" && redir == "") {
if (response == "document") {
document.write(http_req.responseText);
} else {
//Update of innerHTML (but without triggering execution)
//of code found in <script> tags of http_req.responseText
responseObj.obj.innerHTML = http_req.responseText;
loadingObj.style.display = "none";
}
} else if (response != "" && redir != "" && response != "over") {
load_page(redir, "", response, "GET", "");
}
}
}
My guess is that it updates innerHTML but does not ...
add it into the DOM?
do eval?
do the magic?
What is the magic that jQuery possesses that the above library skips out?
Is there a way I can fix the library to cause it to execute the code found in response script tag?
Do you know that this callback is executed in your browser, right? This have nothing to do with your server response. It only executes WHEN your server gives you data back.
You can see proper documentation on XHR here https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
i hope i understand your question correctly:
success : function(data) {
$("#main_page").load('main_page.php');
}
this is the so called "success handler" - it is an event listener, that waits until the http response is received from the server. Javascript works a lot with callback functions which means, you call an action (like the ajax request) and once finished, it calls back another (often anonymous) function.
http://www.w3schools.com/js/js_events.asp
http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/
jQuery uses its own Deferred's to implement callbacks including for its ajax implementation. See the code here: https://github.com/jquery/jquery/blob/master/src/ajax.js
Prerequisites
I have a Website, that displays a page with an input and a button. On the other end is a server that exposes a very basic HTTP API. The API is called like this:
http://127.0.0.1/api/arg1/arg2/arg3
where argX are the arguments. It returns raw HTML. This HTML code needs to be inserted into the Website (another domain). There is a
<div id="container5"></div>
on the website. The HTML needs to be inserted into this container. The code returned by the API is specifically made to be inserted into this container, as it uses CSS classes and scripts from the website, i.e.: the code is not valid for it self.
The Goal
Here is what I have: I've got the API to return what I want, and I got a small JavaScript to run on the website to change the contents of the container:
var element = document.getElementById("container5");
element.innerHTML = "New Contents";
This works so far. Now I need a way to get the HTML from the API to the page. By reading numerous SO questions, it quickly became clear that reading HTML from another URL is close to impossible in JavaScript, due to security constraints.
Is there an easy way to do this with JavaScript or do I need rethink the whole process somehow? One last constraint on my side is that I can only insert JS into the website, I can't - for example - upload a new file to the server.
Edit 1: Workaround!
I solved this for me by using a PHP intermediate file on the requesting server:
<?php
echo file_get_contents('http://example.com');
?>
This will generate a site using the HTML content of any URL. Now the requesting site can read this by using JavaScript:
var getHTML = function ( url, callback ) {
// Feature detection
if ( !window.XMLHttpRequest ) return;
// Create new request
var xhr = new XMLHttpRequest();
// Setup callback
xhr.onload = function() {
if ( callback && typeof( callback ) === 'function' ) {
callback( this.responseXML );
}
}
// Get the HTML
xhr.open( 'GET', url );
xhr.responseType = 'document';
xhr.send();
};
This modifies any element:
var element = document.getElementById("resultpage");
getHTML( 'http://localserver.org/test.php', function (response) {
element.innerHTML = response.documentElement.innerHTML;
});
Checkout CORS https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
also JSONP in same article.
New Restful API's like Google, OpenStreetview use a simple call back mechanism.
Basically you call the API, adding a parameter &callback=my function.
When executing a call to this API, as a result my function is called passing a JSON dataset.
I am trying to create the same mechanisme for a API I am building for my personal use.
As far as I understood my API needs to return a javascript, that calls the function that is passed in a script.
For a test I created this:
function apiCall(URL,values, keyPair,cBackPair) {
// URL specifics URL to call
// keyPair: <keyname>=<key>; leave black if unneeded
// cBacPair: <callBackParametername>=<functionname>
// called is: URL?values&keypair&cBackPair
var request = (keyPair)?'&'+keyPair:'';
request = URL + '?'+ encodeURI(values) + request + '&' + cBackPair;
var script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("src", request);
document.body.appendChild(script);
}
function callAPI() {
apiCall('http://xllent.nl/map/ajax/answer.php','q=one','','s=doit');
}
function doit(result) {
alert(result);
}
To test I call callAPI onload.
The script answer.php is very basic:
<?$s = $_GET['s'];
?>
<script type="text/javascript">
doit('jeroen');
</script>
Later the script would use $s to call the right script, and of course supply user data.
For now I am just trying to get the script doit('jeroen'); to be run. But nothing happens.
Typing javascript:doit('jeroen'); in the browser window gives the result I would expect.
Any suggestions?
Don't surround your javascript with <script> tags. You are not generating a HTML file with a javascript body.. You should think of this as if you're generating a javascript file on fly.
Javascript files also don't start and end with <script>
I want to load a JSON file from my own server containing an array into a javascript Object variable.
I would like to do it at the beginning of page load in a synchronous way because data is needed during page load.
I managed to use jQuery.getJSON but this is asynch ajax and it seems a little overkill.
Is there a way to load JSON in a synch way without doing your own parsing? (more or less like using a <script language="JavaScript" src="MyArray.json"></script>)
Thanks in advance for any help, hope it makes sense since I am a javascript newbie.
Paolo
getJSON() is simply shorthand for the ajax() function with the dataType:'json' set. The ajax() function will let you customize a lot about the request.
$.ajax({
url: 'MyArray.json',
async: false,
dataType: 'json',
success: function (response) {
// do stuff with response.
}
});
You still use a callback with async:false but it fires before it execution continues on from the ajax call.
Here you go:
// Load JSON text from server hosted file and return JSON parsed object
function loadJSON(filePath) {
// Load json file;
var json = loadTextFileAjaxSync(filePath, "application/json");
// Parse json
return JSON.parse(json);
}
// Load text with Ajax synchronously: takes path to file and optional MIME type
function loadTextFileAjaxSync(filePath, mimeType)
{
var xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET",filePath,false);
if (mimeType != null) {
if (xmlhttp.overrideMimeType) {
xmlhttp.overrideMimeType(mimeType);
}
}
xmlhttp.send();
if (xmlhttp.status==200 && xmlhttp.readyState == 4 )
{
return xmlhttp.responseText;
}
else {
// TODO Throw exception
return null;
}
}
NOTE: This code works in modern browsers only - IE8, FF, Chrome, Opera, Safari. For obosolete IE versions you must use ActiveX, let me know if you want that I will tell you how ;)
if you're using a server script of some sort, you could print the data to a script tag on the page:
<script type="text/javascript">
var settings = <?php echo $json; ?>;
</script>
This will allow you to use your data synchronously rather than trying to use AJAX asynchronously.
Otherwise you'll have to wait for the AJAX callback before continuing on with whatever it is you're doing.
I only needed to read a small input file provided in json format and extract a small amount of data. This worked just fine in the circumstances:
json file is in the same directory as the script and is called data.json, it looks something like this:
{"outlets":[
{
"name":"John Smith",
"address":"some street, some town",
"type":"restaurant"
},
..etc...
read the data into js like this:
var data = <?php echo require_once('data.json'); ?>;
Access the data items like this:
for (var i in data.outlets) {
var name = data.outlets[i].name;
... do some other stuff...
}
If RequireJS is an option, you can make it a dependency using requirejs. I use it to mock data in my Angular application. It's essential that some of the mocked data is there before the bootstrap of the app.
//Inside file my/shirt.js:
define({
color: "black",
size: "unisize"
});
Just wrap the json data in a define and declare it as a dependency. More info here: http://requirejs.org/docs/api.html#defsimple
AFAIK jQuery has deprecated synchronous XHR requests because of the potential for performance issues. You could try wrapping your app code up in the XHR response handler as in the following:
$(document).ready(function() {
$.get('/path/to/json/resource', function(response) {
//'response' now contains your data
//your app code goes here
//...
});
});
The modern HTML5 way without jQuery would be:
var url="https://api.myjson.com/bins/1hk8lu" || "my.json"
var ok=await fetch(url)
var json=await ok.json()
alert(a.test)