I was thinking about how to make an instant messaging application, and wanted to not have to send an AJAX request so often (one every .2s), and I came across the following idea:
Send an AJAX request from the user side, to the server.
Only respond once there is a change in the MySQL database
And then send the next AJAX request once the response has been recorded and parsed
I'm aware of how to do the first and third steps, but the second one is going over my head.
I'm assuming that for step 2, I'll need to store the request somewhere, while the PHP script is continuously looping and looking for some changes, and once there is a change, the saved request would be responded to.
EDIT
Didn't know about WebSockets, should've used those.
You could use recursion and query the database every 2 seconds, until you find new data to be served to the user. So basically you could do something like
public function isDataUpdated($lastId) {
$query = "SELECT * FROM `messages` WHERE `messages`.`message_id` > $lastId";
return (bool)(count($this->executeSQL($query)) > 0);
}
public function fetchNewMessages () {
if ($this->isDataUpdated($_GET['last_id'])) {
/* We have new data! Send it to the user */
} else {
sleep(2); // wait for 2 seconds
$this->fetchNewMessages(); // we use recursion to query the database every 2 seconds to find new data
}
}
Although, it is not the best of solutions, it would hopefully work. I would recommend taking a look at Sockets in PHP to better achieve what you want
Related
I am developing a numbers game where users will buy numbers and after 2 days winners will be drawn.
I am using PHP for the backend and jQuery for the frontend.
My problem is when drawing occurred user on different browser can't see same numbers, these draw numbers are being generated by PHP.
I was thinking maybe I can build these game by PHP and Javascript but it looks not easy. Can you guys please suggest some alternative? How can I improve this code to show the same number on the different browser?
I have the idea that it is not possible to generate a random number for each request. Maybe I can save the number in the database and then get this number in PHP such that the number will be unique for each request.
The actual issue is to create the same content for each user in different browsers. Any help would be really appreciated.
Javascript:
var myTimer = setInterval(checkDrawDate, 1000);
function checkDrawDate() {
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();
var time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
var dateTime = date+' '+time;
var x = new Date(dateTime);
var y = new Date("{{$drawDate}}"); //this is laravel variable which contain drawdate e.g. 2017-07-05
if(x >= y){
drawNumber();
}
}
function drawNumber(){
$.get("{{ route('ajaxcomparepowerball') }}",{'gameId': gameid}, function(res){
$('#mybets').html(res.html);
});
}
PHP:
public function ajaxDrawNumber(Request $req){
return rand(0,49);
}
A Cron Job will be needed to implement this functionality. As you are drawing a number on particular time (after $drawDate in your case). So the cron job will execute once in day, check whether $drawDate for each game is today or passed. If condition true, $drawDate <= now, call a function to generate random draw number rand(0,49) and save it to database corresponding to gameid of matched games(having $drawDate <= now).
By doing this, a lot Javascript work will be reduced. In JS, then need to hit an ajax request with gameid to fetch record having draw number for particular game from database. If record not found, it means random number not drawn yet.
I think you are using Laravel, so to schedule tasks in laravel visit here.
Here some possible solutions.
If you need the same data modified for users in real time I think the best option is WebRTC, quick start here. And here a simple example sending strings in real time between clients.
If you also need interaction server to client you could use server-sent events.
You could perform a bidirectional communication between browser and a server using WebSockets. You can send and receive event-driven responses. Using a database you could communicate two clients.
The easiest is using a database to store the information and perform ajax to send data to the server (and database) and server-sent events to send data to the clients.
Basic Server-sent event example:
Javacript:
var evtSource = new EventSource("myserver.php");
evtSource.onmessage = function(e) {
// listening for new messages here
alert(e.data)// e.data is mynumber
}
Php (myserver.php)
<?php
header('Cache-Control: no-cache');
header("Content-Type: text/event-stream\n\n");
while (1) {
//perform a query in your database with your driver
$result = mysql_query("SELECT mynumber FROM mytable WHERE user = 1");
$row = mysql_fetch_assoc($result);
echo $row['mynumber'];//<-- sending mynumber to client
ob_end_flush();
flush();
sleep(1);// <-- this is every second, but you could fire this with ajax or some other event.
}
This code send a number from server to a client that is listening. If a user made a change, one possibility is that client send an ajax to update some value in the database. So, at the same time, the ajax server could send this as an update to clients listening. In that way the whole process is completed.
I think all you need is this. Call a function in every, say 5 seconds or less and fetch data from server and update it in the page.
window.setInterval(function(){
updateNumber();
}, 5000);// set for every five seconds
function updateNumber(){
//ajax code to fetch live data and append the data in the numbers container
}
And dont forget to cross check the data before saving the numbers in the server.
Hope it helps.!!!
To save and maintain users state, key value store like Aerospike can be used. It is very easy to save and retrieve data in key value store. In above case we just have to generate a unique key using gameId, userId and date. And save user's data against the unique key.
To get started with Aerospike php client following is Aerospike php client
If data is present against the unique id for that particular user just return it, else create the new random number save it against the unique key and return it. Please be careful while creating unique key. Instead of using server side date-time please send date in ajax call request so there will not be any issue with time zone. It will be always user's timezone and there will not be any issue if server is in different timezone and user is in different timezone.
function drawNumber(){
$.get("{{ route('ajaxcomparepowerball') }}",{'gameId': gameid,'date':user-timezone-date}, function(res){
$('#mybets').html(res.html);
});
}
Here "user-timezone-date" should be fix date format like 'MM-dd-yy' which will indicate the same day. hours or seconds should not be included while generating unique key otherwise at the time of retrieving the user's state; generating particular unique will be changed every hour or every second and whole purpose of of doing this will be shattered.
I am new to StackOverFlow so I am not able to comment on the answers. In case of corn job as well we have to be careful with time-zones if server and users are in different time zones. Otherwise user's will see different random number before user's day is complete. Please improve answer by commenting on it and suggestions are always welcome.
I am using EXTJs4 and I want to reload the Grid only after a record is Inserted in the Data Base. Currently I am using Task runner to reload the store every 1 minute.
Here is the sample :
var store = grid.getStore();
var refreshTask = {
run: function() {
store.reload();
},
interval: 60 * 1000
};
Ext.util.TaskRunner.start(refreshTask);
I'm not sure how I can write a function only to reload when a data is Inserted in the data base ?
There are various ways to get an instant response from the server once something changes, the most compatible are so-called "Hanging Request".
What you do is you send a request to the server, and the server does not answer instantly. The server instead waits until changes are there (it lets the request "hang", hence the name), and only sends a reply after that, or after a predefined timeout. (This behaviour has to be supported by your server-side code, obviously).
This cannot be implemented with store.load or other store functions on the client side; you will have to use Ext.Ajax.request and evaluate the response manually, e.g. call store.loadRawData from the request callback to load the changed records into the store.
I've got a simple app that fetches a user's complete feed from the Facebook API in order to tally the number of words he or she has written total on the site.
After he or she authenticates, the page makes a Graph call to /me/feed?limit100 and counts the number of responses and their dates. If there is a "next" cursor in the response, it then pings that next URL, which looks something like this:
https://graph.facebook.com/[UID]/feed?limit=100&until=1386553333
And so on, recursively, until we reach the time that the user joined Facebook. The function looks like this:
var words = 0;
var posts = function(callback, url) {
url = url || '/me/posts?limit=100';
FB.api(url, function(response) {
if (response.data) {
response.data.forEach(function(status) {
if (status.message) {
words += status.message.split(/ /g).length;
}
});
}
if (response.paging && response.paging.next) {
posts(callback, response.paging.next);
} else {
alert("You wrote " + words + " on Facebook!");
}
});
}
This works just fine for people who have posts a total of up to 4,000 statuses, but it really starts to crawl for power users with 10,000 lifetime updates or more. Each response from the API is only about 25Kb, but I cannot figure out what's straining the most.
After I've added the number of words in each status to my total word count, do I need to specifically destroy the response object so as not to overload memory?
Alternatively, is the recursion depth a problem? we're realistically talking about a total of 100 calls to the API for power users. I've experimented with upping the limit on each call to fetch larger chunks, but it doesn't seem to make a huge difference.
Thanks.
So, you're doing this with the JS SDK I guess, which mean this runs in the Browser... Did you try to run this in Chrome and then watch the network monitor to see about the response time etc.?
With 100 requests, this also means that the data object/JSON must be about the size of 2.5mb, which for some browsers/machines could be quite challenging I guess. Also, it must take quite a while to fetch the data from FB. What does the user see in the meantime?
Did you think of implementing this in the backend on the server side, and then just passing the results to the frontend?
For exmple use NodeJS together with SocketIO to do it on the server side and dynamically update the word count?
I'm looking for a solution for dealing with an issue of state between models using backbone.js.
I have a time tracking app where a user can start/stops jobs and it will record the time the job was worked on. I have a job model which holds the job's data and whether it is currently 'on'.
Only 1 job can be worked on at a time. So if a user starts a job the currently running job must be stopped. I'm wondering what the best solution to do this is. I mean I could simply toggle each job's 'on' parameter accordingly and then call save on each but that results in 2 requests to the server each with a complete representation of each job.
Ideally it would be great if I could piggyback additional data in the save request similarly to how it's possible to send extra data in a fetch request. I only need to send the id of the currently running job and since this really is unrelated to the model it needs to be sent alongside the model, not part of it.
Is there a good way to do this? I guess I could find a way to maintain a reference to the current job server side if need be :\
when you call a save function, the first parameter is an object of the data that's going to be saved. Instead of just calling model.save(), create an object that has the model data and your extra stuff.
inside of your method that fires off the save:
...
var data = this.model.toJSON();
data.extras = { myParam : someData };
this.model.save(data, {success: function( model, response ) {
console.log('hooray it saved: ', model, response);
});
...
I want to extract some data from the database without refreshing a page. What is the best possible way to do this?
I am using the following XMLHTTPRequest function to get some data (shopping cart items) from cart.php file. This file performs various functions based on the option value.
For example: option=1 means get all the shopping cart items. option=2 means delete all shopping cart items and return string "Your shopping cart is empty.". option=3, 4...and so on.
My XHR function:
function getAllCartItems()
{
if(window.XMLHttpRequest)
{
allCartItems = new XMLHttpRequest();
}
else
{
allCartItems=new ActiveXObject("Microsoft.XMLHTTP");
}
allCartItems.onreadystatechange=function()
{
if (allCartItems.readyState==4 && allCartItems.status==200)
{
document.getElementById("cartmain").innerHTML=allCartItems.responseText;
}
else if(allCartItems.readyState < 4)
{
//do nothing
}
}
var linktoexecute = "cart.php?option=1";
allCartItems.open("GET",linktoexecute,true);
allCartItems.send();
}
cart.php file looks like:
$link = mysql_connect('localhost', 'user', '123456');
if (!$link)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db('projectdatabase');
if($option == 1) //get all cart items
{
$sql = "select itemid from cart where cartid=".$_COOKIE['cart'].";";
$result = mysql_query($sql);
$num = mysql_num_rows($result);
while($row = mysql_fetch_array($result))
{
echo $row['itemid'];
}
}
else if($option == 2)
{
//do something
}
else if($option == 3)
{
//do something
}
else if($option == 4)
{
//do something
}
My Questions:
Is there any other way I can get the data from database without
refreshing the page?
Are there any potential threats (hacking, server utilization,
performance etc) in my way of doing this thing? I believe a hacker
can flood my server be sending unnecessary requests using option=1,
2, 3 etc.
I don't think a Denial of Service attack would be your main concern, here. That concern would be just as valid is cart.php were to return HTML. No, exposing a public API for use via AJAX is pretty common practice.
One thing to keep in mind, though, is the ambiguity of both listing and deleting items via the same URL. It would be a good idea to (at the very least) separate those actions (or "methods") into distinct URLs (for example: /cart/list and /cart/clear).
If you're willing to go a step further, you should consider implementing a "RESTful" API. This would mean, among other things, that methods can only be called using the correct HTTP verb. You've possibly only heard of GET and POST, but there's also PUT and DELETE, amongst others. The reason behind this is to make the methods idempotent, meaning that they do the same thing again and again, no matter how many times you call them. For example, a GET call to /cart will always list the contents and a DELETE call to /cart will always delete all items in the cart.
Although it is probably not practical to write a full REST API for your shopping cart, I'm sure some of the principles may help you build a more robust system.
Some reading material: A Brief Introduction to REST.
Ajax is the best option for the purpose.
Now sending and receiving data with Ajax is done best using XML. So use of Web services is the recommended option from me. You can use a SOAP / REST web service to bring data from a database on request.
You can use this Link to understand more on Webservices.
For the tutorials enough articles are available in the Internet.
you're using a XMLHttpRequest object, so you don't refresh your page (it's AJAX), or there's something you haven't tell
if a hacker want to DDOS your website, or your database, he can use any of its page... As long as you don't transfer string between client and server that will be used in your SQL requests, that should be OK
I'd warn you about the use of raw text response display. I encourage you to format your response as XML or JSON to correctly locate objects that needs to be inserted into the DOM, and to return an tag to correctly handle errors (the die("i'm your father luke") won't help any of your user) and to display them in a special area of your web page
First, you should consider separating different parts of your application. Having a general file that performs every other tasks related to carts, violates all sorts of software design principles.
Second, the first vulnerability is SQL injection. You should NEVER just concatenate the input to your SQL.
Suppose I posted 1; TRUNCATE TABLE cart;. Then your SQL would look like:
select itemid from cart where cartid=1; TRUNCATE TABLE cart; which first selects the item in question, then ruins your database.
You should write something like this:
$item = $_COOKIE['cart'];
$item = preg_replace_all("['\"]", "\\$1", $item);
To avoid refreshing, you can put a link on your page. Something like, Refresh
In terms of security, it will always pay to introduce a database layer concerned with just your data, regardless of your business logic, then adding a service layer dependent on the database layer, which would provide facilities to perform business layer actions.
You should also take #PPvG recommendation into note, and -- using Apache's mod_rewrite or other similar facilities -- make your URLs more meaningful.
Another note: try to encapsulate your data in JSON or XML format. I'd recommend the use of json_encode(); on the server side, and JSON.parse(); on the client side. This would ensure a secure delivery.