Passing Mysql data to PHP array then to javascript - javascript

Let me start by explaining the situation:
I have a MySql table that contains several columns, of which a user id, a race id, a lap time, a lap number and I want to put this information into an array in PHP which I will then send to a java script.
My JavaScript array should end up looking like this :
first row:
[laptime1 user1, laptime2 user1, laptime3 user1,...]
second row:
[laptime1 user2, laptime2 user2, laptime3 user2,...]
Here's my current situation:
I first tried to test this situation for a single user and ran into lots of problems because my lap times in MySql are floats and when using json_encode it turned everything into strings, which did not work for my javascript as it started outputting the wrong values.
For example:
The first value was "8" instead of "84,521", then the second value was "4", etc..)...
Sadly, I found a potential solution with the numeric check option, but cannot use it as my hosting runs a PHP version that doesn't support it.
So I found the following solution, which I fiddled with a bit and that works for a single user (it might look messy to you, I'm really a beginner and punching above my weight, but it works) :
$query = doquery("SELECT racelaptime,userid FROM {{table}} WHERE raceid='1' ORDER BY racelap", "liverace");
while(($result = mysql_fetch_array($query))) {
$data[] = (float)$result['racelaptime'];
}
$script = $script . "\nvar myArray = new Array(";
foreach ($data as $key => $value){
if ($key < (count($data)-1)){
$script = $script . $value . ',';
}
else {
$script = $script . $value . ");\n";
}
}
This outputs an array in JavaScript that looks like this :
myArray=[84.521,83.800,81.900]
Which is great, as this is exactly what my java script requires as input (time in seconds, separated by commas for each lap).
Now I would like to implement the multiple user element but I'm stumped as to how I can work that out...
My MySQL query is still sorted by race lap but I also kind of need to sort the data by user id as I want all the laps of each user sorted in 1 row, Also, the user id is unknown to me and can vary (depends which user posts the time) so I can't really do a "if userid==1 save this here and then go to next one".
Should I use a foreach statement in the while loop that stores the data, but how can I tell him to store all the laps by the same user in the first row (and the next user in the second row, etc...) without using tons of SQL queries ?
If you can offer a more elegant solution than my current one for passing the PHP array to JavaScript, I would be more than happy to make changes but otherwise a simple solution using the current "setup" would be great too (hope it's all clear enough).
Any help would be very much appreciated, thanks in advance !

For multiple user element I would use a multidimensional array >
$query = doquery("SELECT racelaptime,userid FROM {{table}} WHERE raceid='1' ORDER BY racelap", "liverace");
// Loop the DB result
while(($result = mysql_fetch_array($query))) {
// Check if this ID is already in the data array
if(!array_key_exists($result['userid'], $data)){
// Create array for current user
$data[$result['userid']] = array();
}
// Add the current race time to the array (do not need to use the float)
$data[$result['userid']][] = $result['racelaptime'];
}
// Echo json data
echo json_encode($data);
Now what you need to do on the Javascript side when handling this array is to go through each of the user
$.each(data, function(key, value){
// Use parseFloat to keep the decimal value
alert(key + ' Has the following values - ' + value);
// If you want to display the racing values you simply
$.each(value, function(k, parseFloat(v)){
alert(v);
})
})
Is this what you needed or am I completely out of the scope?

Related

How to search Steam game API JSON output?

I am working with following APIs:
http://api.steampowered.com/ISteamApps/GetAppList/v0002/?format=json
https://store.steampowered.com/api/appdetails?appids=GAMEID
(gameid example: "730" - counter strike)
My goal with both of these is to search them for data. For example I want the first API to give me a name of a game based on it's ID and the second one to give me specific information about a game for example if it has trading cards (id:29 in the API).
I tried a few things but I am kinda lost on this beacuse I don't really understand JSON so I would really appreciate some help.
I am open to both PHP and JS solutions.
IN PHP, you can use the json_decode() function to convert JSON data into an array. You can them access the values as you do for a classic array :
$appID = 730 ;
$url = 'https://store.steampowered.com/api/appdetails?appids=' . $appID ;
$content = file_get_contents($url) ; // retrieve the JSON data string from the website
$data = json_decode($content, true); // convert the JSON string into PHP array
echo $data[$appID]['data']['name'] ; // Counter-Strike: Global Offensive
var_dump($data[$appID]['data']['is_free']); // bool(true)

increment value in database using PHP and AJAX

I am trying to make value +1 in database every time use use button.
my function in HTML:
function onClick(arg){
alert("thx fo click");
$.ajax({
type: 'POST',
url: 'data.php',
data: {
'arg': arg,
},
success: function(response) {
}
});
}
arg means value of button and it is a ID for a row in the database
and PHP:
<?php
$link = mysql_connect($servername, $username, $password);
$id = $_POST['arg'];
$sql = "UPDATE Buttons(SUMA) SET SUMA = SUMA + 1 WHERE ID = '$id'";
$conn->query($sql);
mysql_close($link);
?>
And that make nothing. How can i fix it?
You have several syntax errors here.
First and foremost though, check out mysqli_ (or PDO) and start using that instead of mysql_
For why to use mysqli_ - MySQL vs MySQLi when using PHP
Comparing mysqli_ and PDO - https://websitebeaver.com/php-pdo-vs-mysqli
With that out of the way....
You're defining your database connection without selecting a schema, but don't reference your schema in the query, meaning mysql won't know what to update. Either reference your schema in the connection or in each query. Also check on your table name, is it really Buttons(SUMA)?
You defined your database connection as $link, but are using $conn to attempt the query. Probably a 'typo' from copy and paste. Be careful of this...
As Artistic Phoenix mentioned, you have to make sure you're column cannot be set to NULL, and starts at 0 to begin. While you're at it and we're going through, make sure your datatype is set to int for the increment count.
After making those changes if you don't have success, I'd try running your query outside your code in a DB manager to ensure that portion is having the intended affect on your data, before looking at the errors in your code.
I'm guessing the arugment is passing correctly to your script, but to confirm, you can always echo it on the backend, and to be doubly sure alert() it in JS before it's passed through.
Take the time to go through that reading, update your script to use mysqli_ or PDO, and if you're still having troubles, I'm more than happy to jump back in here and help you further.
What is 1 + NULL it's still NULL.
IF you didn't default the column to '0' , then you can't increment it.
This can best be shown in a simple DB fiddle
Starting Null:
CREATE TABLE t(
id INT(10),
v INT(10)
);
INSERT INTO t (id)VALUES(1);
SELECT * FROM t;
UPDATE t SET v = v+1 WHERE id=1;
SELECT * FROM t;
In Both selects you will get a value of null for v as seen below in the fiddle:
https://www.db-fiddle.com/f/m1vgKpov1oiRJEfZEgmk1j/0
In simple terms, you cannot add 1 (or any number) to a NULL value. Well you can but it's still null. null + 1 = null
Starting 0:
CREATE TABLE t(
id INT(10),
v INT(10) default 0
);
INSERT INTO t (id)VALUES(1);
SELECT * FROM t;
UPDATE t SET v = v+1 WHERE id=1;
SELECT * FROM t;
In this case the first Select return 0 for v and the second returns 1 for v. As seen in the modified fiddle.
https://www.db-fiddle.com/f/m1vgKpov1oiRJEfZEgmk1j/1
Also (SQLInjection)
As I said in the comments:
What if arg = "' OR 1 --"
Or in other words don't inject user variables (or any clientside data) into your SQL or it winds up looking like this:
UPDATE `Buttons(SUMA)` SET SUMA = SUMA + 1 WHERE ID = '' OR 1 --'"
Which will increment every row in your DB that is not null. Basically the ' closes the other quote, then OR 1 is always true(for every row). Unfortinalty I cant show the -- comment part in the fiddle (it comments out the second select), but here is the end result.
https://www.db-fiddle.com/f/m1vgKpov1oiRJEfZEgmk1j/3
This is why we use prepared statements. This example is somewhat trivial but I have seen login code on here I was able to bypass simple by putting "' OR 1 LIMIT 1 --'" in, and with offset you could iterate though each user. They were looking for 1 row to be returned on the match of a username and password.
A few other things:
Table name Buttons(SUMA) is that really the name, as it will only work if escaped with the backtic. As I did in the above SQLInjection example.
$link = mysql_connect($servername, $username, $password); are these defined, the open tag is right above them. I generally chock that up to simplified example code. But it's worth asking. Obviously you can't connect to the DB if those are undefined.
Cheers!

Check MySQL if data already exists, if not, INSERT. [PHP+jQuery Ajax]

I'm having trouble creating php code that would insert values into MySQL database but only if they don't already exist.
I send array from javascript to PHP file using $.ajax type POST.
Do I need additional 'SELECT' query to check if values already exist?
PHP File(Works, inserts values):
<?php
SESSION_START();
include('config.php');
if(isset($_POST['predictedMatches'])&&$_SESSION['userid']){
$predictedMatches=$_POST['predictedMatches'];
$userid=$_SESSION['userid'];
}else die("ERROR");
$sql="";
foreach($predictedMatches as $predictedMatch){
$sql.="INSERT INTO predictions(result,userFK,matchFK,tournamentFK) VALUES('".$predictedMatch['result']."','".$userid."','".$predictedMatch['id']."','".$predictedMatch['tourid']."');";
}
if($conn->multi_query($sql) === TRUE){
echo "OK";
}else{
echo "Error: " . $sql . "<br>" . $conn->error;
}
$conn->close();
?>
Use the ON DUPLICATE KEY UPDATE feature. It won't insert, if the primary key exists. But you have to update some value, so use the column which is in no index or in the least indexes () in your case probably result). Your primary key has to be composted out of the three FKs:
ALTER TABLE `predictions` ADD PRIMARY KEY( `userFK`, `matchFK`, `tournamentFK`);
PHP-Code, just the SQL statment (I'm a Java Guy, so i tried my best)
$sql.="INSERT INTO predictions (result, userFK, matchFK, tournamentFK) "
."VALUES('".$predictedMatch['result'] ."','".$userid."','"
.$predictedMatch['id']."','".$predictedMatch['tourid']."') "
."ON DUPLICATE KEY UPDATE result = result ;";
To know if the query was inserted you have to look at the affected row count:
1 Row - Insert
2 Rows - Update
Take a look at $conn->affected_rows after the query.
Performance
INSERT ... ON DUPLICATE KEY UPDATE is definitively faster than a SELECT and INSERT but it's slower than an INSERT of just the needed datasets. The update is done in the database, even if it is the same value. Unfortunately there is no ON DUPLICATE KEY UPDATE INGNORE. If you have a lot of inserts, that will result in updates, than it may be better to use a cache, lookup values in an array and compare with the array before inserting. Only use the ON DUPLICATE KEY UPDATE as fallback.

Construct mySQL query from dynamic select boxes

I've already been able to construct a mySQL query using select boxes. Starting with ajax to PHP like so.
html/js (relevant parts)
var call = true;
switch(parseInt($(this).val())) {
case 1:
cat_code ="ager";
sortv = "database_percent";
sorto = "asc";
break;
case 2:
cat_code ="ager";
sortv = "database_percent";
sorto = "desc";
break;
default:
cat_code ="ager";
sortv = "value";
sorto = "asc";
break;
}
if(call) {
$.ajax({
url: 'all_get_2.php',
type: 'GET',
dataType: 'JSON',
data: {cat_code: cat_code, sortvalue: sortv ,sortorder:sorto},
success: function(data) {
//stuff
}
})
PHP (relevant parts...just an example)
$whereCategory = isset($_GET['cat_code'])? "{$_GET['cat_code']}" : '';
$sortvalue = isset($_GET['sortvalue'])? "{$_GET['sortvalue']}" : '';
$sortorder = isset($_GET['sortorder'])? "{$_GET['sortorder']}" : '';
$sql = "select count(guid) from full_db2 where '{$whereCategory}' = '{$sortvalue}'' and example = '{$sortorder};";
$result = $dbh->query($sql)->fetchAll(PDO::FETCH_ASSOC);
header('Content-type: application/json');
echo json_encode($result);
All's well. I mixed up some variables in this illustration, but that's not the issue. This returns the count for the attributes that the user selected from the selects. The selects are dynamically generated based on what the user selected in the previous select.
What if I wanted users to be able to select a bunch more attributes to add to the query. So, for example, instead of finding the count for the number of entries in the database (users) who's age is more than 40, they could add on more to this like users with age greater than 40 and married and have children.
I considered basically adding an option to add another set of select boxes (e.g., click a "+" and new set appears), but I quickly realized that I wouldn't be able to figure out how many selects were out there and a logical way to create a query.
What's the best possible way to allow users to select a (theoretically) unlimited number of attributes to construct in an single mySQL query?
I would use the HTML <select> & <option> tags to present the various SQL conditional operators (AND, OR, >, <, =, !=) along with your field/table names, then concatenate them together to build your query.
As mentioned in the comments, you could utilize the array capabilities like name="checkbox[]" and submit it as an HTML form (POST or GET) to simplify concatenation.
You will want to escape and sanitize anything sent to the database to avoid SQL injection as HTML pages can be edited client side. Without sanitization your entire database will be accessible to a savvy user. This can be as simple as verifying that the array contents matches actual table names or one of the conditional operators and then discarding if it doesn't match. Escaping using mysqli::escape_string (http://php.net/manual/en/mysqli.real-escape-string.php) is also a good idea.
I ended up having to redo this question after I was able to figure out a few things. Here's how I progressed and check the accepted answer to see how it all is done together:
Create array for PDO from variables passed from jquery

trouble converting 2d php array to 2d javascript array

I have really done what I think is a not-code-review-passing hack to pass a 2-dimensional array from PHP to Javascript. The outer array has elements, and each of its elements is an array.
Each inner array consists of 4 fields from my database records. The inner array elements are: the name of a town, its latitude and its longitude, and an integer index.
Is the code working? Yes. But I'm hating the fact that I am 99% convinced that, as a fairly raw beginner, there is a much better way to create then pass a 2d array from PHP to Javascript and I need to know how, as I hacked this together through trial-and-error and reading lots of SO posts, and did not create this from a priori know-how, wisdom or confidence.
Each outer array element is an array that (needs to) look like this:
top
array:
[0] = ["Campbell", 37.21, 122.0, 0]
[1] = ["Sunnyvale", 37.54, 121.37, 1]
[2] = ["Saratoga", 37.24, 122.001, 2]
[3] = ......etc. etc...........
Note that the 2nd level arrays have a string, then a float, then another float, then an integer.
Here's the code in PHP that packages my database records into a 2-d PHP array (error checking, other code is not shown, for clarity):
$result = mysql_query($query);
$numrows = mysql_num_rows($result);
$outerArray = array();
for($i = 0; $i < $numrows; $i++)
{
$theRow = mysql_fetch_row($result);
$city = $theRow[1];
$lat = $theRow[22];
$lng = $theRow[23];
$outerArray[] = array($city, $lat, $lng, $i);
}
$latLngValues = json_encode($outerArray);
// EDIT: ADDED TO TELL ME WHAT THIS 2d ARRAY ACTUALLY LOOKS LIKE
var_dump($latLngValues);
In the onload handler for my web page, I call a javascript function and pass this array:
<body onload='handleLoad(<?php echo $latLngValues ?>)'>
Here is my handleLoad():
function handleLoad( latLng2dArray )
{
for (var i = 0; i < latLng2dArray.length; i++)
{
var town = latLng2dArray[i];
var latitude = Number(town[1]);
var longitude = Number(town[2]);
// I USE THE DATABASE RECORD'S NUMBERS TO CREATE A Gmaps LatLng
var myLatLng = new google.maps.LatLng(latitude, longitude);
}
There's probably a cleaner, and/or more efficient, way to do this.
For example, I found that if I did not use the Number() function to 'force' my database numbers into a number, the call to "new google.maps.LatLng(latitude, longitude)" was giving me NaN.
So I'm hoping more experienced people can let me know a cleaner way. While this code works, I hacked at it for a day through trial and error.
EDIT: I used a var_dump() in my php code to see what the 2d array "$latLngValues" looks like just before it's passed to my onload handler, and "$latLngValues" looks like this:
string(133) "[["Campbell","37.2724","-122",0],["Sunnyvale","37.2724","-122",1],["LosGatos","37.2607","-122",2],["Saratoga","37.2607","-122.046",3]]"
I want to point out this: in my database, the data type I used is 'float' for the latitude and longitude. Not sure how/why the var_dump shows them as a string (not floats) while the integer index is treated correctly, and not a string.
No one offered a better coding strategy so for now, I'm going with the existing code above -- it aint pretty but it works. I'll post back if a more-correct way is found.

Categories