I've recently started exploring using AJAX for a small project, and I've had reasonable success though it's not as smooth as I would like.
The Basic setup is that an applications named ProphetX which interfaces with Excel to show stock market prices. Prices are updated as they change in Excel. Using VBA I save the data from the spreadsheet into an SQL08 DB every time a price updates. This could sometimes be a few times per second.
Using PHP on an Apache server I connect to the SQL DB and load the data into tables, and a javascript function to keep updating the information once every second. I've noticed however that at times the page will simply hang if you already have it up, or load a blank screen if you pull it up, particularly when data is being updated rapidly. So to the meat of my question: Is there something in my code which could be causing this hiccup? I doubt it is congesting the network or server resources as I've been monitoring them and they seem low.
Also I used WireShark to monitor network traffic, and when I load up the page and it shows blank in the browser, I can see the HTML being sent from the server to my machine.
Any help / coding style criticism is much appreciated, source code below.
Index.php:
<html>
<head>
<script type="text/javascript" src="update.js"></script>
</head>
<body onLoad = update()>
<font size = +2>
<?php
echo "
<div id = 'marketData'></div>
";
?>
</font>
</body></html>
Update.js:
function update()
{
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)
{
document.getElementById("marketData").innerHTML=xmlhttp.responseText;
}
}
//URL needs a var to be passed via get for code to function in IE, thus Math.Random().
//I am also confused by this requirement.
xmlhttp.open("GET","update.php?i="+ Math.random(),true);
xmlhttp.send();
var t = setTimeout("update()", 3000);
}
Update.php:
<?php
//connect to database
error_reporting(0);
sqlsrv_configure("WarningsReturnAsErrors", 1);
$server = "myServer";
$db = "myDB";
$connectionInfo = array("Database"=>"$db, "UID"=>"user", "PWD"=>"pass");
$conn = sqlsrv_connect($server, $connectionInfo);
if($conn)
{
echo "<font size =-1 color=green>Connection Established<br></font>";
}
else
{
echo"Connection not established:<br>";
print_r(sqlsrv_errors());
}
//Func calls sqlsrv_query($conn, [$symbol],[$DatabaseName])
$stmt = sqlsrv_query($conn,query(array('sym1','sym2','sym3'), "electronic") );
errorCheck($stmt);
printTables("Electronic Commodity Prices", $stmt);
$stmt = sqlsrv_query($conn,query(array('sym1','sym2','sym3'), "floor") );
errorCheck($stmt);
printTables("Floor Commodity Prices", $stmt);
$stmt = sqlsrv_query($conn,query(array('sym1','sym2','sym3',... ,sym19), "natgas") );
errorCheck($stmt);
printTables("Natural Gas Commodity Prices", $stmt);
sqlsrv_free_stmt($stmt);
sqlsrv_close( $conn);
//This function prints out the tables
function printTables($tableName, $stmt)
{
echo
"
$tableName<hr>
<table cellspacing ='5' cellpadding = '5'>
<tr>
<th>Symbol</th>
<th>Product</th>
<th>Last Price</th>
<th>Change</th>
<th>High Price</th>
<th>Low Price</th>
<th>Previous Price</th>
<th>Trade Time</th>
</tr>
";
while($row=sqlsrv_fetch_array($stmt))
{
echo
"
<tr>
<td>$row[symbol]</td>
<td><font size =+3 color = blue>$row[description]</font></td>
<td>$row[last]</td>
<td><font size =+5> $row[change]</font></td>
<td>$row[highPrice]</td>
<td>$row[lowPrice]</td>
<td>$row[previousprice]</td>
<td>" . date("j M g:i",strtotime($row['tradetime'])) . "</td>
</tr>
";
}
echo"</table><hr>";
}
function query($symbols, $db)
{
$count = count($symbols);
$stmt =
"
select distinct id,symbol,description,last,change,highPrice,lowPrice,previousprice,tradetime from $db
where ";
for($i = 0; $i< $count; $i++)
{
$stmt .= "id in (select MAX(id)from $db where symbol ='$symbols[$i]') ";
if($i != $count-1)
{
$stmt.= "or ";
}
}
$stmt .= "order by description asc";
// id in (select MAX(id)from $db where symbol ='$symbols[0]')
// or id in (select MAX(id)from $db where symbol ='$symbols[1]')
// or id in (select MAX(id)from $db where symbol ='$symbols[2]')
// order by description asc
return $stmt;
}
function errorCheck($stmt)
{
if( $stmt=== false )
{
echo "Error in statement preparation/execution.\n";
die( print_r( sqlsrv_errors(), true));
}
}
?>
Without running your code locally, I would suggest you look into DB locking issues. If you are really updating your DB records a number of times a second, and trying to load you query page ever three seconds (your timeout is set to 3000, which is three seconds). If your query page takes longer than three seconds to load because of DB locking issues then your browser may having blocking issues, as it is waiting for the response from one request while firing a new ajax request.
You could try putting some timeout code in your php query page.
Related
I have a simple PHP page that sends a query to a mySQL database and displays the data onto a HTML table.
How can I get it to do this every 5 seconds? Currently it does this upon the page loading. The database will have changing data, so am trying to get the code to refresh every 5 seconds to keep the table updated.
How might I go upon doing this?
You need to use a client-side scripting language such as JavaScript to have a webpage do something after it has been served to a client.
Specifically, you will want to use timers and AJAX calls. You may also find the jQuery library useful for abstracting AJAX calls however it is not a requirement.
You need to use javascript ajax. For example ,
<script>
function loadXMLDoc()
{
var xmlhttp;
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)
{
document.getElementById("myDiv").innerHTML=xmlhttp.responseText; // your div
}
}
xmlhttp.open("GET","getdatabase.php",true); //your php file
xmlhttp.send();
}
window.setInterval(function(){
loadXMLDoc();
}, 5000);
</script>
Then in html , you must have a div with specified ID(myDiv) Fpr example:
<body>
<div id="myDiv"></div>
</body>
Then in getdatabase.php you must fetch the value from the database and echo it out. For example,
<?php
$con=mysqli_connect("example.com","peter","abc123","my_db");// Check connection
if (mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$result = mysqli_query($con,"SELECT * FROM Persons");
echo "<table border='1'>
<tr>
<th>Firstname</th>
<th>Lastname</th>
</tr>";
while($row = mysqli_fetch_array($result)) {
echo "<tr>";
echo "<td>" . $row['FirstName'] . "</td>";
echo "<td>" . $row['LastName'] . "</td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
?>
Hope it works , see more at www.w3schools.com/
Use javascript timers. From there-on u can periodically run the SQL command to read the databases.
If this problem still arises, I can post some example code.
I've changed the code with the selection boxes to the below:
<html>
<head>
<script type="text/javascript">
function loadXMLDoc() {
var xmlhttp;
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) {
document.frm.modelSelection.innerHTML=xmlhttp.responseText;
}
}
var makevalue=document.frm.makeSelection.value;
xmlhttp.open("GET","http://www.autodeal.co.za/newsite/model-selection?ajaxmake="+makevalue,true);
xmlhttp.send();
}
</script>
</head>
<body>
<?php
$dbName = "F:/Domains/autodeal/autodeal.co.za/wwwroot/newsite/db/savvyautoweb.mdb";
// Throws an error if the database cannot be found
if (!file_exists($dbName)) {
die("Could not find database file.");
}
// Connects to the database
// Assumes there is no username or password
$conn = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", '', '');
?>
<form action="index.php?option=com_content&view=article&id=99" method="post" name="frm">
<select name="makeSelection" onchange="loadXMLDoc()">
<?php
//Loads the Makes from the database into a dropdown
$resultMake = odbc_exec($conn, "SELECT DISTINCT Make FROM Vehicle ORDER BY Make") or die (odbc_errormsg());
while ($rowMake = odbc_fetch_array($resultMake)) {
echo "<option value='$rowMake[Make]'>$rowMake[Make]</option>";
}
?>
</select><br />
<select name="modelSelection">
</select><br />
<select name="yearSelection">
<option>2004</option>
<option>2005</option>
<option>2006</option>
<option>2007</option>
<option>2008</option>
<option>2009</option>
<option>2010</option>
<option>2011</option>
<option>2012</option>
<option>2013</option>
<option>2014</option>
</select><br />
<select name="priceSelection">
<option>< 5000</option>
<option>5000 - 20 000</option>
<option>20 000 - 50 000</option>
<option>50 000 - 100 000</option>
<option>100 000 - 200 000</option>
<option>200 000 - 300 000</option>
<option>300 000 - 400 000</option>
<option>400 000 - 500 000</option>
<option>50 000 - 1 000 000</option>
<option>> 1 000 000</option>
</select>
<input type="submit" name="submit" value="Go">
</form>
</body>
</html>
Hi,
I've updated the code to reflect the answers below, but now, when you make the first selection, the Model selection box remains empty.
modelSelection.php
<?php
$dbName = "F:/Domains/autodeal/autodeal.co.za/wwwroot/newsite/db/savvyautoweb.mdb";
// Throws an error if the database cannot be found
if (!file_exists($dbName)) {
die("Could not find database file.");
}
$conn = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", '', '');
//loads the models based on the makes selection into a dependant dropdown
if (isset($_REQUEST['ajaxmake'])) {
$resultModel = odbc_exec($conn, "SELECT Model FROM Vehicle WHERE Make = '".$_REQUEST['ajaxmake']."'") or die (odbc_errormsg());
while ($rowModel = odbc_fetch_array($resultModel)) {
echo "<option value='$rowModel[Model]'>$rowModel[Model]</option>";
die(); //I'm not sure where to put this because I assume this is the reason why this selection must be first
}
}
?>
As far as I can see, the problem is that you are loading the whole request response text inside a select button. I've looked at your request response and it is responding the whole page with the models loaded, so basically it is getting all options and loading them on the Model select box, because you are inserting the whole page on the model select box.
You have multiple options here:
You can create a page that only loads the Model options, so have a file which has only this part:
$dbName = "F:/Domains/autodeal/autodeal.co.za/wwwroot/newsite/db/savvyautoweb.mdb";
// Throws an error if the database cannot be found
if (!file_exists($dbName)) {
die("Could not find database file.");
}
$conn = odbc_connect("Driver={Microsoft Access Driver (*.mdb)};Dbq=$dbName", '', '');
//loads the models based on the makes selection into a dependant dropdown
if (isset($_REQUEST['ajaxmake'])) {
$resultModel = odbc_exec($conn, "SELECT Model FROM Vehicle WHERE Make = '".$_REQUEST['ajaxmake']."'") or die (odbc_errormsg());
while ($rowModel = odbc_fetch_array($resultModel)) {
echo "<option value='$rowModel[Model]'>$rowModel[Model]</option>";
}
}
And change the page you are calling through ajax to point to that page:
xmlhttp.open("GET","newpage.php?ajaxmake="+ makevalue,true);
The other option, and the one I suggest you is to look into some javascript library, such as jQuery which has functions to easen your work.
If you include jQUery library, adding the select name as id="makeSelection" and id="modelSelection" you could write a javascript function like this:
jQuery(document).ready(function(){
jQuery("#makeSelection").change(function(){
jQuery("#modelSelection").load("?ajaxmake="+ makevalue + #modelSelection option");
});
});
BTW! Be aware that you may have a huge security problem in your sql queries, since people can attack you through the ajaxmake variable, and truncate/drop your tables or anything. I suggest you to sanitize and validate the data coming from your requests, specially if you post some sensitive data like your database tables on the internet!!! If you want to know more about SQL Injection (how this security issue is called): How can I prevent SQL injection in PHP?
I am not sure why you have html included in your ajax processing file. Usually you keep a .php file consisting only of php code and then you can be sure no html or script code are being included (which is currently happening in your page now).
For one, try to change your model dropdown code to:
<?php
//loads the models based on the makes selection into a dependant dropdown
if (isset($_REQUEST['ajaxmake'])) {
echo "<select name='modelSelection'>"; //select tag placed here
$resultModel = odbc_exec($conn, "SELECT Model FROM Vehicle WHERE Make = '".$_REQUEST['ajaxmake']."'") or die (odbc_errormsg());
while ($rowModel = odbc_fetch_array($resultModel)) {
echo "<option value='$rowModel[Model]'>$rowModel[Model]</option>";
}
echo "</select><br>";
die(); //<-- the die placed here will not execute the rest of
//the code and also all the options will be populated
}
?>
I am beginning to learn PHP + AJAX + SQL. I cannot seem to crack the syntax issue I am running into. I am running the latest WAMP version on a server in my network as the test environment.
I have the following script in my INDEX.PHP (from W3Schools.com):
<script>
$(document).ready(function() {
$('#submit').click(function() {
str = document.getElementById("cn").value;
if (str=="")
{
document.getElementById("txtHint").innerHTML="No name typed, returning all rows ";
str="all";
};
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)
{
document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
}
};
xmlhttp.open("GET","getcustomer.php?q="+str,true);
xmlhttp.send();
});
});
</script>
I then have a server side script called GETCUSTOMER.PHP which contains (in part) the following:
<?php
$q = $_GET['q'];
echo "The variable contains = ".$q; **<--- this shows me on the browser the correct variable value is passed to the server side script**
$con = mysqli_connect('localhost','phpuser','abc123','learnphp');
if (!$con)
{
die('Could not connect: ' . mysqli_error($con));
};
mysqli_select_db($con,"PHP_AJAX_Demo");
if ($q == "all") {
$sql="SELECT * FROM customers";
} else {
$sql="SELECT * FROM customers WHERE 'Company' = '" . $q . "'";
};
$result = mysqli_query($con,$sql);
When my main form submits with a "blank" value for COMPANY it works fine as the "str=all" is executed and returns to the browser all rows in the CUSTOMERS table. When I submit it with a value (that exists in the table) I get no rows back. I also get no errors back.
The syntax came from W3 and it works on their demo. What am I missing? Thanks in advance!
You're putting single quotes around your column name when single quotes are used to indicate the beginning and end of a string value. Use backticks instead. Change:
$sql="SELECT * FROM customers WHERE 'Company' = '" . $q . "'";
to
$sql="SELECT * FROM `customers` WHERE `Company` = '" . $q . "'";
Note that this script is open to SQL injection and that you should be using prepared statements.
Haven't found this exact situation on here, so I figured I'd ask. I have some JavaScript that, using AJAX, is attempting to call a PHP file, execute the PHP script, and return a concatenated PHP variable through xmlhttp.responseText, then alert that response.
JS
function queryDB() {
var xmlhttp;
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)
{
alert(xmlhttp.responseText);
}
}
xmlhttp.open("GET","php/location.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send();
}
PHP
<?php
$con = mysql_connect("<THIS DATA HIDDEN FOR SECURITY PURPOSES, IT IS CORRECT");
if (!$con) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("gpstracks", $con);
$bus = $_GET['bus'];
$query = "SELECT lat, lon from tracksarchive where runnerid = '$bus' ORDER BY time DESC LIMIT 1;";
$latlon = mysql_query($query);
while ($row = mysql_fetch_array($latlon, MYSQL_ASSOC)) {
$lat = $row['lat'];
$lon = $row['lon'];
}
$result = $lat . ", " . $lon;
echo $result;
mysql_close($con);
?>
Yes, I know that mysql_ has been replaced by mysqli_, I'll deal with that later. When I execute the PHP on its own (using a form submit) - it displays the correct values from the table, but when I alert the xmlhttp.responseText - I only get the comma and space - no passed variables. Any idea what I'm doing wrong? Help is much appreciated.
Sidenote: I know the preferred method for AJAX calls these days is jQuery - but a component of the page this JavaScript is on doesn't function when I use jQuery.
when I alert the xmlhttp.responseText - I only get the comma and space - no passed variables
You're not performing your GET properly; in your JavaScript you have
xmlhttp.open("GET","php/location.php",true);
i.e. you performed a GET request without a URI query string.
In your PHP you have
$bus = $_GET['bus'];
i.e. you're GETting this data from the URI query string, except none was passed, so this will be empty, so
$query = "SELECT lat, lon from tracksarchive where runnerid = '$bus' ORDER BY time DESC LIMIT 1;";
doesn't work as expected.
You really wanted to do something like
xmlhttp.open(
"GET",
"php/location.php?bus="+window.encodeURIComponent(foobar),
true
); // foobar your value for `bus`
Further, you'll need to do some server-side sanitisation of $bus, as it stands you're open to SQL injection.
As you send request by GET method, you need to manually add the parameter bus to the URL. So, rewrite
xmlhttp.open("GET","php/location.php",true);
to
xmlhttp.open("GET","php/location.php?bus=value",true);
You should pass "bus" in on the PHP file URL.
I have written a simple application that displays a list of candidates for a job, then, upon clicking a hire button, should alter a database to reflect the newly hired candidate and display the rest as unhired. However, the function is not working properly. The problem I am having is the AJAX function never seems to provide a response, and I cannot figure out why. The database is also not getting updated. My files are below.
The line document.getElementById("errors").innerHTML+=xmlhttp.readyState+" "+xmlhttp.status+"<br>"; is updating a div at the bottom of my html page, showing that the the readyState is 4 and the status is 200, which should mean that the AJAX function returned properly, but the echo'd response is not being displayed. Even when I remove all code from the new_hire.php file and simply make the file echo "hello";, nothing is returned in the responseText.
resumes.php:
<html>
<head>
<script type="text/javascript">
function new_hire(name){
var xmlhttp;
if (window.XMLHttpRequest){
xmlhttp=new XMLHttpRequest();
}
else{
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function(){
document.getElementById("errors").innerHTML+=xmlhttp.readyState+" "+xmlhttp.status+"<br>";
//this line, when removed, does not change anything. I left it in for debugging purposes.
document.getElementById("errors").innerHTML+=xmlhttp.responseText;
if (xmlhttp.readyState=4 && xmlhttp.status=200){
var others = xmlhttp.responseText.split("|");
for (i=0;i<others.length;i++){
tag = others[i].replace(" ","_");
document.getElementById(tag).innerHTML="";
}
}
}
xmlhttp.open("POST","new_hire.php",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send("hiree="+name.replace(" ","%20")+"&position=Salespeople");
var name_tag = name.replace(" ","_");
document.getElementById(name_tag).innerHTML="(Current Employee)<br>";
}
</script>
</head>
...
</html>
new_hire.php (AJAX response file):
<?php
$hiree = $_POST['hiree'];
$pos = $_POST['position'];
$con = mysql_connect("host.name","user","pass") or die('Could not connect: ' . mysql_error());
mysql_select_db("dbname",$con);
$clear = mysql_query("UPDATE $pos SET employed=false WHERE 1=1;");
mysql_fetch_array($clear);
$reset = mysql_query("UPDATE $pos SET employed=true WHERE Name='$hiree';");
mysql_fetch_array($reset);
$people = mysql_query("SELECT Name FROM $pos WHERE employed=false;");
$array = array();
while ($row = mysql_fetch_array($people)){
array_push($array,$row['Name']);
}
mysql_close($con);
$response = join("|",$array);
echo $response;
?>
Please note that your if statement is not using the comparison operator == but rather the assignment operator = so you are using: if (xmlhttp.readyState=4 && xmlhttp.status=200) instead of if (xmlhttp.readyState==4 && xmlhttp.status==200)