I have come across this problem before and expect to do so again: I want to run a subtotal calculation in both javascript and PHP. I may want to change the calculation at some point.
It needs to run in javascript to maximise the speed of the calculation, so that the user knows what to expect.
It needs to run in PHP so that I am getting a valid subtotal which a malicious user cannot interfere with.
As such:
If I only run the calculation on the client-side (in javascript), a malicious user may hack the javascript and change the subtotal.
If I only run the calculation on the server-side (in PHP), an AJAX call would have to be waited on for the user to get their updated subtotal.
So I want to perform the calculation on both sides. The only way I have seen this done is by programming the calculation in PHP and programming the calculation in separate javascript.
My question is, what pattern, technique or technology would people recommend that I use to create the calculation on the server-side and make it compatible with javascript when it is sent to the client-side?
An idea I had, for example, was a PHP array for the calculation, which gets translated into PHP code and javascript code, e.g:
array(
array(type => "operand", "name" => "variable_A"),
array(type => "operator", "name" => "multiply"),
array(type => "operand", "name" => "variable_B"),
)
This might convert into PHP:
return $variable_A * $variable_B;
And into Javascript:
return variable_A * variable_B;
That's an example operational pattern. I don't know what real ones would look like if they exist.
ajax?
you can pass all the variable entered with javascript and leave the process server based.
or i misunderstand your question?
The way I think about your problem is like you described it: do double calculation.
And I believe that's how the "big boys" do it.
Example: Add up two numbers.
So you have a code like this:
HTML snippet:
<form method="post" action="/add.php">
<input id="firstOperand" name="firstOperand" placeholder="First operand"/>
<input id="secondOperand" name="firstOperand" placeholder="Second operand"/>
<input type="submit" onclick="doCalculation()" value="Add"/>
</form>
<div id="result" />
Your JS might look like:
function doCalculation() {
var first = parseInt(document.getElementById('firstOperand').value);
var second = parseInt(document.getElementById('secondOperand').value);
var result = first + second;
// the minimum amount of error checking
if isNan('result') return false;
document.getElementById('result').innerHTML = result;
// Now use some framework (like jQuery) to make an Ajax call and pass the result to callback.
Framework.Ajax('/add.php?format=json', 'POST', {first: first, second: second}, callback);
return false;
}
function callback(response) b
var res = response.json.result;
var resultEl = document.getElementById('result');
var errorEl = document.getElementById('error');
// if our result is not correct, we want to update the user on it
if (res != parseInt(resultEl.innerHTML)) {
Framework.removeClass(errorEl, 'hidden');
}
document.getElementById('result').innerHTML = res;
}
Of course, your PHP result page (add.php) would return json with the result. The added value here is that you can also return a plain HTML result (like if js is disabled).
Your callback could also check if there was an error in the returned result and display that error message too. Or if the result times out, display a notification that the "result" is not saved. But that's out of the scope of the question, I guess (at least, out of the scope of the answer).
Note: this is just the code off the top of my head, not tested, written directly in the answer box, probably a few things should be done better.
Related
I'm looking to create a page, which has a set of buttons. These buttons are each tied to different php functions (the things done by these functions have to be done server side). Basically, all the coding is done in php. The php has all the objects, the constants, all the information needed in the page. But all the actions need to be initiated by the user, by clicking the buttons.
But here comes the problem: how can I efficiently mix those php functions with my buttons? Right now I'm using ajax, javascript and jquery but the way I do it feels controversial, here's what I mean:
var continueFight;
$("#playerAttack").click(function() {
if (continueFight) {
AJAX actions here
}
one of the ajax actions is a $.post, directed to the following page:
<?php
//some fight calculations
if ($fightOver)
echo "<script>continueFight=false</script>";
?>
In the above, some php calculations are done to decide whether the fight is over, and if it is, it echoes some Javascript and returns it (through the AJAX request) to the main page, which will cause the button to stop running in the future.
This feels very messy. Is there a better way to mix PHP with buttons?
I don't see why echoing a script element. Just echo a value (e.g., 1 or nothing), and from the success callback act according to the response:
<?php
//some fight calculations
echo $fightOver;
?>
var continueFight;
$("#playerAttack").click(function() {
if (continueFight) {
$.post(url, {}, function(response) {
continueFight = !!response; // cast response to boolean
}
}
})
Your approach is exactly as you assumed. You have to treat your PHP as isolated events and not something that's keeping a constant record. Suppose you're making a game. You store the state of the game and any relevant data in a database common to the players, typically using a token passed back and forth.
Your entire game's interactions should be handled client side. By that I mean listeners that send requests to php via ajax. PHP should ONLY return state responses to interpret with js, it should NOT return html or anything goofy like that.
You can add provisions to your php to validate state server side to prevent js manipulation, but that's probably not a huge concern of yours at this point.
Looks like everyone else basically said the same thing but with code samples so I'll cut this here. If you have specific questions, feel free to ask and I may update.
EDIT
State responses would be something like an object, integer to represent a boolean, integer range, score, or anything else used as a simple response to trigger a more complex action in javascript.
So suppose you have an attack. Suppose you send the request to PHP to have it decide whether or not the attack was successful and if so, what kind of damage did it do. You might expect to get a response like this from PHP:
$response = array(
'success' => 1,
'damage' => 200,
'enemy_id' => 4
);
echo json_encode($response);
from javascript, assuming your jQuery ajax success was assigning the response to data you could evaluate the response like this:
//assume generically that this object represents the damagable players
var players = {
0: {
health: 200
},
1: {
health: 300
},
2: {
health: 30
},
3: {
health: 750
},
4: {
health: 10
}
};
// and assume this is in your success function in your ajax call
if(data.success == 1)
{
//successful attack. cause damage
players[data.enemy_id].health -= data.damage;
if(players[data.enemy_id].health <= 0)
{
// do something to kill enemy
}
}
Point is, you should return absolutely minimal data to the browser and let the client side handle all the game actions. PHP is just used to sync the game or fetch resources that aren't available to the client.
Don't echo chunks of JavaScript back to the page. Write the JavaScript in JavaScript, and pass a flag back from PHP to tell the S what to do:
JavaScript:
var continueFight;
$("#playerAttack").click(function() {
if (continueFight) {
$.post('scriptname.php', function(data) {
continueFight = data.continueFight;
});
}
});
PHP:
<?php
//some fight calculations
echo json_encode(array('continueFight' => !$fightOver));
That's as easy as it gets. Ajax requires a lot of typing, unfortunately.
I have a set of 5 HTML dropdowns that act as filters for narrowing results returned from a mySQL database. The three pertinent filters are for "Province", "Region", and "City" selection, respectively.
I have three functions:
findSchools(), which runs when any of the filters (marked with CSS class .filter) are changed, and fetches the results via AJAX from a PHP script. Once that is done, two other functions are called...
changeRegionOptions(), which, upon changing the "Province" filter, and updates the available options using the same method as the first function, but posting to a different script.
changeCityOptions(), which runs if the "Region" filter was changed, and updates options, again using the same method.
The problem is that since I want these AJAX functions to run simultaneously, and they by nature run asynchronously, I've tried using $.when to control the execution of the functions, but it doesn't fix the problem.
The functions run, but the Region and City filters return blank (no options); the FireBug report shows absolutely no output, even though the POST request went through. The posted parameter for filter_province gets sent normally, but the one for region gets cut off at the end -- it sends as filter_region=, with no value passed. So I'm presuming my logic is wrong somewhere. The code is below:
// When any of the filters are changed, let's query the database...
$("select.filter").change(function() {
findSchools();
});
// First, we see if there are any results...
function findSchools() {
var sch_province = document.filterform.filter_province.value;
var sch_region = document.filterform.filter_region.value;
var sch_city = document.filterform.filter_city.value;
var sch_cat = document.filterform.filter_category.value;
var sch_type = document.filterform.filter_type.value;
$.post("fetch_results.php",
{ filter_province : sch_province,
filter_region : sch_region,
filter_city : sch_city,
filter_category : sch_cat,
filter_type : sch_type },
function(data) {
$("#results").html("");
$("#results").hide();
$("#results").html(data);
$("#results").fadeIn(600);
}
);
// Once the results are fetched, we want to see if the filter they changed
was the one for Province, and if so, update the Region and City options
to match that selection...
$("#filter_province").change(function() {
$.when(findSchools())
.done(changeRegionOptions());
$.when(changeRegionOptions())
.done(changeCityOptions());
});
};
This is just one of the ways I've tried to solve it; I've tried using an IF statement, and tried calling the functions directly inside the general select.filter.change() function (after findSchools(); ), but they all return the same result.
Any help with this would be great!
You need to turn async to false. After that, your code will be executed line by line.
For example like this, before calling $.post
$.ajaxSetup({async:false});
Try this .hope this is what you were expecting. jsfiddle->sample code
Im not sure if this is possible, but at the moment I have a form on my page where users can insert their interests, beneath that form are 3 PHP variables (Which dont currently show at first as there is no value assigned to them).
When a user enters an interest and clicks submit, my AJAX takes over, populates the table and then reloads the page so the Variable now shows as it has a value.
Is it possible to not have to refresh the page, so I can say "if success $var = 'value';"?
I hope this doesnt sound too confusing, thanks
Since you're already using AJAX, why don't you just do the logic using Javascript? If you're using jQuery, have a success callback function execute the code you want.
The problem with sending data from AJAX to PHP is that PHP is a server side language, while AJAX is a client side one. By the time your browser sees the page, the PHP has been entirely executed and returned to you as HTML / CSS / Javascript etc.
No, you can't. By the time the HTML has rendered/displayed in the browser, PHP will most likely have long since finished generating the HTML in the first place. You could round-trip the values through an AJAX handler and then populate the places in your page where the values are displayed, but when why bother round-tripping? Just have the AJAX call fill in the values right then and there.
It is absolutely possible, and quite easy to do. Just make another php script and call it from your form page's javascript (I'm going to assume you're using jQuery):
$('#mysubmit').click(function() {
$.getJSON(
'form_ajax.php', // This is the php file that will be called
{ formVar1: $('#form-var-1').val() }, // Add all your form data here
function(data) {
// This is the function that is called after the php script is
// done executing. The 'data' variable will contain the $data
// array you see in the following php file.
}
);
});
I prefer to use JSON, but other approaches are just as good. Check out the documentation for getJSON() and ajax(). Your php file would look something like this:
<?php
$data = array();
if ($_SERVER['REQUEST_METHOD'] == "POST") {
$data['formVar1'] = $_POST['formVar1'];
}
echo json_encode($data);
?>
Of course, yours would probably do a lot more with the form data. Also, theres plenty of other approaches so go explore for the one the best suits your needs.
I have the following jquery code:
while (count < 31) {
window['cday_' + count] = <?php echo $day_1 ?>;
window['tday_' + count] = (window['cday_' + count] * formfig) / formfig2;
count++;
}
But I need $day_1 in the php echo statement to reflect the variable "count", so in theory it should be something like "echo $day_count". Is it possible to pass the var to php?
php & jquery coding:
$i=0;
while ($i < $num) {
${"day_$i"}=mysql_result($result,$i,"datavalue");
$i++;
}
?>
<script type="text/javascript">
var chart1;
var count=1;
var formfig=17;
var formfig2=2;
function chartdraw(){
while (count < 31) {
window['cday_' + count] = <?php echo $day_1 ?>;
window['tday_' + count] = (window['cday_' + count] * formfig) / formfig2;
count++;
}
The short answer here is no.
To understand what's possible, you need a deep understanding of what's going on. Your PHP code is building an HTML document (with embedded JavaScript) and sending it on to the web browser. Once the web browser (which is, of course, running on the user's machine, not your server) renders that page, it will execute the javascript. This is when the javascript variables begin to actually mean something. Until then, they are just text getting sent across the network. This point is long after the PHP code has finished running. Your server has already closed down that php instance as it sent the code to the user.
Keeping that in mind, you can send the value of a javascript variable (or any number of other things) back to your server with something called an ajax request. Essentially, this will send some information (the variable's value, and the name of the page you want) back to your server, which will in turn cause your server to build a new web page, which can have PHP code in it. That web page's content will get returned to another bit of javascript you can provide -- called a 'callback' -- which can take the page created by the second php script and make use of it. This is, of course, fairly resource intensive.
Unless you plan to do something that ONLY PHP can do, I would recommend finding a way to do as much of your logic as possible in javascript. This alleviates all these complex problems and keeps all the hard work on the user's machine.
If you can structure your code so your php code provides all the data the javascript code needs before the php finishes running, you can get away without doing anything fancy with ajax. Here's an example:
<script type="text/javascript">
var days = {};
<? for($day = 0; $day < 30; $day++) { ?>
days.<? echo $day ?> = "<? echo get_day_info($day) ?>";
<? } ?>
</script>
What this will do is create a javascript object called days. Then it will fill in days.i for i from 0 to 30. It assumes you have a function called get_day_info($day) which takes a day and returns the info for that day. I'm assuming here that you're dealing with strings -- if not, you will need to remove the quotes, and possibly do other things to wrap the data depending on what format it takes.
I belive the only way is using ajax. http://api.jquery.com/jQuery.ajax/
Not without changing your approach significantly.
The problem is that PHP exists entirely on your server, where javascript exists in the browser. PHP does really know anything about javascript. PHP will completely render your page before any javascript has been run at all. So there is no way to get this value back in easily.
You can use ajax in order to run javascript which can load data or hit URLs on your server, but you cant simply substitute javascript variables in PHP. The reason you can do it with PHP variables is because the PHP actually is generating the javascript.
Have javascript store the value in a hidden field and pick up the value with PHP that way?
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.