I Have the following code:
<?php
error_reporting(E_ALL);
// connect to your MySQL database here
$dbhandle = mysql_connect('xxx', 'xxxx', 'xxxx');
$selected = mysql_select_db("xxxx",$dbhandle);
// Get the winner data
function setWinner(){
$sql = 'UPDATE user SET winner = 1 WHERE id=(SELECT id FROM user ORDER BY RAND())';
$query = mysql_query($sql) or die (mysql_error());
echo $query;
}
// Get the winner data
function getWinner()
{
$sql = 'SELECT id, fullname, email, number FROM user WHERE winner = 1';
$query = mysql_query($sql) or die (mysql_error());
if(mysql_num_rows($query) == 1) {
$user = mysql_fetch_assoc($query);
} else {
// If there is no winner yet, automatically create one
setWinner();
// Recall the function which should now find a winner
$user = getWinner();
}
return $user;
}
$winner = getWinner();
print_r($winner);
?>
Trying to work with g4vroche's answer but getting this error: You can't specify target table 'user' for update in FROM clause
I used this for a competition to select a random user from the database, but i now need it to look through all the users to see if there's a user that's winner column equals 1 and if there isn't one it should select the random user and update that users winner column with 1.
Any Help greatly appreciated.
I'm using the mysql_query() function just because you used it in your example. You should read up on PDO and implement that instead.
Per my comment above,
require_once "connect_to_mysql.php";
// look for records with `winner` set to 1
$result = mysql_query('SELECT id, fullname, email, number FROM user WHERE winner = 1 LIMIT 1') or die (mysql_error());
if (mysql_num_rows($result) < 1) { // if no records were found, pick a random row
$result = mysql_query('SELECT id, fullname, email, number FROM user ORDER BY RAND() LIMIT 1');
}
I don't know what your winner column actually stores, but assuming it's a boolean, which may contains only 0 or 1, you could do this in a single query :
SELECT id, fullname, email, number FROM user ORDER BY winner DESC, RAND() LIMIT 1;
Which will :
Sort all records on winner column, making rows hanving winner = 1 firsts
Sort equals records with RAND()
So you will get and random result, priority being given to records having winner column equals to "1".
EDIT
I missunderstood your need.
You have two different process here
Get the winner
Set the winner
You should probably split that into two function / methods
// Get the winner data
function getWinner()
{
$sql = 'SELECT id, fullname, email, number FROM user winner=1';
$query = mysql_query($sql);
mysql_num_rows($result) == 1) {
$user = mysql_fetc_assoc($query);
return $user;
}
return false;
}
function setWinner()
{
$sql = 'UPDATE user SET winner=1 ORDER BY RAND() LIMIT 1';
mysql_query($sql);
}
// Call this one time
setWiner();
// Call this any time you want to get the winner's data
$winner = getWinner();
A more lazy approach, will be to make the getWinner() function to call setwinner if there is no winner yet :
// Get the winner data
function getWinner()
{
$sql = 'SELECT id, fullname, email, number FROM user winner=1';
$query = mysql_query($sql);
mysql_num_rows($result) == 1) {
$user = mysql_fetc_assoc($query);
} else {
// If there is no winner yet, automatically create one
setWinner();
// Recall the function which should now find a winner
$user = getWinner();
}
return $user;
}
That's up to your context, but on general point of view it's bad practice, because a function which looks like reading data (getSomething) will, under some circumstances, also alter data (call to setWinner().
Related
I want to have a row with a column called: 'seen', then this column will have either a default of no value or a 'yes' value.
So..
Grab one row where it hasn't been 'seen' before.
Update the above row 'seen column' to say 'yes'.
If all rows have the value of 'yes' then a notice/error displays:
You have successfully completed all numbers.
I've tried the best I can do achieve it, but it's not working. I think my logic in tackling this may be incorrect?
include 'DB.php';
$con = mysqli_connect($host,$user,$pass);
$dbs = mysqli_select_db($databaseName, $con);
// Grabs one row where it hasn't been seen before
$query = mysqli_query("SELECT number, association, image_file, skeleton, sound, colour, comments FROM num_image WHERE seen='' ORDER by rand() LIMIT 1");
// Updates the above row with the 'seen' column saying 'yes''
$query = mysqli_query("UPDATE num_image SET seen = yes");
// Fetches Result
$thestuff = mysqli_fetch_row($query);
$seenme=$_POST['seen']; // get value of 'seen' column
$result = mysqli_query("SELECT * FROM num_image where seen=$seenme");
// Trying to delivery a message if the enitre 'seen' column is ALL yes.
while($row = mysqli_fetch_row($result))
{
if($row['seen'] == 'yes')
{ // All numbers seen
echo 'You have successfully completed all numbers.';
echo json_encode($thestuff);
}
else
{ // Show numbers
echo json_encode($thestuff);
}
}
Does the SELECT and UPDATE row also have to be an if statement?
Cheers
You have to escape the value in the Update sentence:
$query = mysqli_query("UPDATE num_image SET seen = 'yes' ");
I am creating a website in php to log ping pong scores for my school, and currently the player who wins will log the WinnerID, LoserID, PointsFor, PointsAgainst. I have two tables with the following relationships.
Table: users
user_ID (PK)
username
Elo
Table: games
game_id (PK)
WinnerID (FK)
LoserID (FK)
PointsFor
PointsAgainst
My insert statement in the php file is:
INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')"
Here is what I have tried, but it doesn't display the scores correctly.
SELECT min(u.username) 'Username', COUNT(g.WinnerID) 'Wins', sum(g.PointsFor) 'Points For', sum(g.PointsAgainst) 'Points Against', u.Elo 'Ranking'
from games g
LEFT JOIN users u
on g.WinnerID = u.user_id
Group by g.WinnerID
As you can see by the image above, the points for and points against totals don't add up. Currently, it only displays the stats for whoever was winner. Meaning if PlayerA wins 21-5, it will show up from the select statement, but PlayerB will not show a score of 5-21. Any help is appreciated.
PHP code for page to enter scores:
if(isset($_POST['btn-post']))
{
$opponent = $_POST["opponent"];
//$opponent = array_key_exists('opponent', $_POST) ? $_POST['opponent'] : false;
$userscore = mysql_real_escape_string($_POST['userscore']);
$oppscore = mysql_real_escape_string($_POST['oppscore']);
if($userscore != $oppscore)
{
if($userscore > $oppscore)
{
$Winner_ID = $_SESSION['user'];
$query = mysql_query("SELECT user_id FROM users WHERE username = '".$opponent."'");
$result = mysql_fetch_array($query) or die(mysql_error());
$Loser_ID = $result['user_id'];
$query1 = mysql_query("SELECT Elo FROM users WHERE user_id=".$_SESSION['user']);
$result1 = mysql_fetch_array($query1) or die(mysql_error());
$winnerRating = $result1['Elo'];
$query2 = mysql_query("SELECT Elo FROM users WHERE user_id=".$Loser_ID);
$result2 = mysql_fetch_array($query2) or die(mysql_error());
$loserRating = $result1['Elo'];
$rating = new Rating($winnerRating, $loserRating, 1, 0);
$results = $rating->getNewRatings();
if(mysql_query("UPDATE users SET Elo = " . $results['a'] . " WHERE user_id=".$_SESSION['user']))
{
}
else
{
?>
<script>alert('There was an error while entering winners(user) ranking...');</script>
<?php
}
if(mysql_query("UPDATE users SET Elo = " . $results['b'] . " WHERE user_id=".$Loser_ID))
{
}
else
{
?>
<script>alert('There was an error while entering losers(opp) ranking..');</script>
<?php
}
}
elseif($oppscore > $userscore)
{
$Loser_ID = $_SESSION['user'];
$query = mysql_query("SELECT user_id FROM users WHERE username = '".$opponent."'");
$result = mysql_fetch_array($query) or die(mysql_error());
$Winner_ID = $result['user_id'];
//get rating from user table in database
$query1 = mysql_query("SELECT Elo FROM users WHERE user_id=".$_SESSION['user']);
$result1 = mysql_fetch_array($query1) or die(mysql_error());
$loserRating = $result1['Elo'];
$query2 = mysql_query("SELECT Elo FROM users WHERE user_id=".$Loser_ID);
$result2 = mysql_fetch_array($query2) or die(mysql_error());
$winnerRating = $result1['Elo'];
$rating = new Rating($winnerRating, $loserRating, 1, 0);
$results = $rating->getNewRatings();
$results = $rating->getNewRatings();
if(mysql_query("UPDATE users SET Elo = " . $results['b'] . " WHERE user_id=".$_SESSION['user']))
{
}
else
{
?>
<script>alert('There was an error while entering losers(user) ranking...');</script>
<?php
}
if(mysql_query("UPDATE users SET Elo = " . $results['a'] . " WHERE user_id=".$Winner_ID))
{
}
else
{
?>
<script>alert('There was an error while entering winners(opp) ranking...');</script>
<?php
}
}
if(mysql_query("INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')"))
{
?>
<script>alert('Your scores were successfully entered');</script>
<?php
}
else
{
?>
<script>alert('There was an error while entering your score...');</script>
<?php
}
}
else
{
?>
<script>alert('There cannot be a tie in ping pong, please re-enter your scores...');</script>
<?php
}
}
?>
Your query fails because it doesn't take into account the rows where the player loses. You can fix that by using unions. The following query should do what you want:
SELECT username AS "Username",
SUM(wins) AS "Wins",
SUM(PF) AS "Points For",
SUM(PA) AS "Points Against",
elo AS "Ranking"
FROM (
(SELECT users.user_ID,
users.username AS username,
COUNT(games.WinnerID) AS wins,
SUM(games.PointsFor) AS PF,
SUM(games.PointsAgainst) AS PA,
users.Elo AS elo
FROM users, games
WHERE games.WinnerID = users.user_ID
GROUP BY users.user_ID)
UNION ALL
(SELECT users.user_ID,
users.username AS username,
0 AS wins,
SUM(games.PointsAgainst) AS PF,
SUM(games.PointsFor) AS PA,
users.Elo AS elo
FROM users, games
WHERE games.LoserID = users.user_ID
GROUP BY users.user_ID)
) AS t
GROUP BY username
ORDER BY user_ID;
Note that in the "losing query" the field PointsAgainst should be counter as the player's "points for" and vice-versa.
Try it as an inner join, and get rid of the MIN() on the username column:
SELECT u.username, COUNT(g.WinnerID),
SUM(g.PointsFor), SUM(g.PointsAgainst), u.Elo
FROM users u, games g
WHERE u.user_id = g.WinnerID
GROUP BY u.username, u.Elo;
Also, before anyone else takes you to task, you should be using mysqli instead of mysql (or better yet, PDO) and you should be using prepared statements instead of dynamic SQL.
Your
INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')
query contains the $userscore and $oppscore values in a potentially wrong order. The $Winner_ID and $Loser_ID may change in your conditional processing, but $userscore and $oppscore are not similarly flipped at that time.
Also your conditional structure is in general unnecessarily verbose. It seems like you should be able to just determine the winner and loser ID and score first, and then do all your processing once instead of resorting to error-prone copy-paste duplication of near-identical code.
I currently save game scores using this code:
function SubmitScore()
{
global $result, $db;
$playername = $db->real_escape_string(strip_tags($_POST["playername"]));
$score = $db->real_escape_string(strip_tags($_POST["score"]));
$fbusername = $db->real_escape_string(strip_tags($_POST["fbusername"]));
$gamelevel = $db->real_escape_string(strip_tags($_POST["gamelevel"]));
$query1 = "SELECT * FROM leaderboard WHERE playername = '$playername'";
$query2 = "INSERT INTO leaderboard (playername, score,fbusername,gamelevel) VALUES ('$playername', $score,'$fbusername','$gamelevel')";
$query3 = "UPDATE leaderboard SET score = $score WHERE playername = '$playername'";
$scores = $db->query($query1);
if ($scores->num_rows == 0)
{
$db->query($query2);
$result = "0:New entry";
}
else
{
$row = $scores->fetch_object();
$oldscore = $row->score;
if ($score > $oldscore)
{
$db->query($query3);
$result = "0:Successful update";
} else
$result = "0:Score was lower than before";
}
}
The playername column is unique and inserts a new row for a new player but only updates an existing players score if it is higher than the existing one.
This is fine just for high scores and one level but I need to also need to store the users facebook name and the multipule game levels.
Is it possible to have playername and gamelevel columns to be unique, whereby I can obtain player 1 level 1, player 1 level 2 etc;
bearing in mind I also have to keep the high score as well.
John
MySQL supports a combination of columns to be defined as a unique key. If you remove the index for playername and add a new one for playername+level you are set as far as MySQL goes.
This is how it's done with SQL:
ALTER TABLE `leaderboard` DROP INDEX `unique_index`;
ALTER TABLE `leaderboard` ADD UNIQUE `unique_index`(`playername`, `gamelevel`);
I've recently implemented a custom liking and disliking feature for my comics site. I'd like to give users the ability to "Take back" their selection by "unclicking" the like or dislike button.
My function works by:
1) Passing button value (id = 'like' or id = 'dislike') via Jquery to
php script
2) script will first check if an ip exists in the database against
that given comic id... if not it will insert user's IP and current
comic ID... if it does, it originally said "you've already voted"... but now to implement "unliking", I will just have it run a delete query
3) then it will get total current likes for that comic id and
increment.
The way I think it can be done is if the user presses the button again, I basically run the opposite query... delete that user's vote from the table given that comic id... then decrement total likes for that image in the comics table.
So my questions are,
1) Is doing an insert query if they press a button once, then a delete
query if they "deselect" that same choice the best way to implement
this? Couldn't a user spam and overload the database by continuously
pressing the like button, thereby constantly liking and unliking?
Should I just implement some sort of $_SESSION['count'] for that ID?
2) If I'm storing a certain IP... what happens if several uniques
users happen to use the same computer at... let's say a netcafe... it
will always store that user's IP. Is storing against the IP the best
way to go?
Code if you need a reference:
<?php
include 'dbconnect.php';
$site = $_GET['_site'];
$imgid = intval($_GET['_id']);
$input = $_GET['_choice'];
if ($site == "artwork") {
$table = "artwork";
}
else {
$table = "comics";
}
$check = "SELECT ip, tablename, imgid FROM votes WHERE ip = '".$_SERVER['REMOTE_ADDR']."' AND tablename = '$table' AND imgid = $imgid";
$result = $mysqli->query($check);
if ($result->num_rows == 0) {
//Insert voter's information into votes table
$sql = "INSERT INTO
votes (ip, tablename, imgid)
VALUES
(\"".$_SERVER['REMOTE_ADDR']."\", \"$table\", $imgid)
ON DUPLICATE KEY UPDATE
imgid = VALUES(imgid)";
if (!$mysqli->query($sql)) printf("Error: %s\n", $mysqli->error);
/*while ($row = $result->fetch_assoc()) {
echo "you've inserted: " . $row['ip'] . ", " . $row['tablename'] . ", " . $row['imgid'] . ".";
}*/
$result = $mysqli->query("SELECT like_count, dislike_count FROM $table WHERE id = $imgid");
//put the counts into a list
list($likes, $dislikes) = $result->fetch_array(MYSQLI_NUM);
if ($input == "like") {
$sql = "UPDATE $table SET like_count = like_count + 1 WHERE id = $imgid";
$mysqli->query($sql);
$likes++;
}
else if ($input == "dislike") {
$sql = "UPDATE $table SET dislike_count = dislike_count + 1 WHERE id = $imgid";
$mysqli->query($sql);
$dislikes++;
}
}
else { //"unlike" their previous like for that given image id
$sql = "DELETE FROM
votes
WHERE (ip, tablename, imgid) =
(\"".$_SERVER['REMOTE_ADDR']."\", \"$table\", $imgid)";
if (!$mysqli->query($sql)) printf("Error: %s\n", $mysqli->error);
$result = $mysqli->query("SELECT like_count, dislike_count FROM $table WHERE id = $imgid");
//put the counts into a list
list($likes, $dislikes) = $result->fetch_array(MYSQLI_NUM);
if ($input == "like") { //remove like
$sql = "UPDATE $table SET like_count = like_count - 1 WHERE id = $imgid";
$mysqli->query($sql);
$likes--;
}
else if ($input == "dislike") {
$sql = "UPDATE $table SET dislike_count = dislike_count - 1 WHERE id = $imgid";
$mysqli->query($sql);
$dislikes--;
}
}
echo "Likes: " . $likes . ", Dislikes: " . $dislikes;
mysqli_close($mysqli);
?>
1) I would say yes, use a count feature to limit the number of attempts they can hit the button in succession. Probably wouldn't have much trouble unless they hit really high numbers, I believe a simple loop would do fine.
2) I would not store just the IP. I would try and use something more than just the IP as an Identifier, like the IP and the session cookie - that way it's unique. However on the look back to the server you would have to parse the entry from the db. Or perhaps the mac address. I'm not sure if you have access to that or not. How can I get the MAC and the IP address of a connected client in PHP?
I'm sure there's another way but conceptually that's how I see it working.
At the moment im sending scores and data to my database from my flash game, though every level completed is a new record.
feilds are set out like l1Score,l2Score,l3Score
im trying to figure out how to update records if the field ipAddress and playerName match the current $varibles.
UPDATE highscores SET l2Score = '$l2Score' WHERE ipAddress = "$ipAddress" && playerName = '$playerName'
I was thinking somthing along these lines, but could someone point me in the right direction please!
First you want to perform a query to check if there is already a score in place for that user & IP.
$sql = "SELECT * FROM highscores WHERE ipAdress = '$ipAdress' AND playerName = '$playerName'";
$result = mysql_query($sql, $con);
$row = mysql_fetch_assoc($result);
Now, if $row is empty then you want to insert a new record, else you want to update a previous record.
if($row == "")
{
$query = "INSERT INTO highscores (l2score, ipAdress, playerName) VALUES ('$l2score', '$ipAdress', '$playerName'";
} else {
$query = "UPDATE highscores SET l2Score = '$l2Score' WHERE ipAdress = '$ipAdress' AND playerName = '$playerName'";
You may need to edit this to fit with the specific query that you need.