I'm making an auction type website that as you can imagine is supposed to delist products as they expire. the expiration is simply stored as MySQL datatype DATE.
so check_items.php:
<?php
function check_items()
{
$con = mysql_connect('localhost','heh','heh');
mysql_select_db('heh_db',$con);
$q = mysql_query("select last_check from ran_last",$con) or die("Check ran_last 1");
$r = mysql_fetch_assoc($q);
//if((time()-strtotime($r['last_check'])) >(60*60*17))//check only once every 17 hours
if(true)
{
$q2 = mysql_query("select * from Item where expired=0");
$remove = array(); $count=0;
while($row = mysql_fetch_assoc($q2))
{
if(strtotime($row['time_expire'])<time())
{
echo("strtotime: ".strtotime($row['time_expire'])." time: ".time());
$remove[$count] = $row['ItemID'];
$count++;
}
}
mysql_free_result($q2);
foreach($remove as $next)
{
echo($next);
$q3 = mysql_query(sprintf("select * from Item where ItemID='%s'",$next)) or die("check items outer query foreach");
$r3 = mysql_fetch_assoc($q3);
$q4 = mysql_query(sprintf("update Item set expired='1' where ItemID='%s'",$r3['ItemID']));
if(isset($r3['bidderID']))
{
$f1 = mysql_query(
sprintf("insert into notifications(userID,item_name,ItemID,type,info) values('%s','%s','%s','%s','%s')",
$r3['bidderID'],
$r3['item_name'],
$r3['ItemID'],
"BUY",
sprintf("You have won the bidding for this item. Contact the seller for details",
$r3['userID'],
$r3['ItemID'])
),$con
);
$f2 = mysql_query(
sprintf("insert into notifications(userID,item_name,ItemID,type,info) values('%s','%s','%s','%s','%s')",
$r3['userID'],
$r3['item_name'],
$r3['ItemID'],
"SELL",
sprintf("User has won the bidding for your item. You are encouraged to contact each other",$r3['bidderID'],
$r3['ItemID'])
),$con
);
}
else
{
$f1 = mysql_query(
sprintf("insert into notifications(userID,item_name,ItemID,type,info) values('%s','%s','%s','%s','%s')",
$r3['userID'],
$r3['item_name'],
$r3['ItemID'],
"SELL",
sprintf("Unfortunately no one bid on your item. You can view expired items from your userpage and re-upload",
$r3['userID'])
),$con
);
}
mysql_free_result($q3);
}
$done = mysql_query("insert into ran_last values()");
}
mysql_free_result($q);
}
?>
The script, fully functional, stores the last time it did an update and should only run once every 17 hours. Right now it runs whenever the function is called. Basically whenever I list a product it automatically gets delisted.
Uh, why are you doing it this way? you can do the filtering in PHP and save yourself a LOT of hassle:
SELECT ItemID
FROM Item
WHERE (expired = 0) AND (time_expire < (SELECT last_check FROM last_ran))
Plus, you're not even checking for this value when you do the real expiry check:
if(strtotime($row['time_expire'])<time())
^^^^^^--- shouldn't this be $r['last_check']?
Related
I am trying to create a Secret Santa system using a PHP page and a MySQL database to store the details so if someone forgets their match they can re-request it.
Step 1: I created a random number generator based on the number of people in the list in the database.
Count Function:
$maxSQL = "SELECT COUNT(id) as total FROM secretsanta";
$maxRS = mysqli_query($conn, $maxSQL);
$maxQuery = mysqli_fetch_array($maxRS);
$maxpersons = $maxQuery['total'];
Then the Random Number Generator:
$assigned = rand(1,$maxpersons);
Step 2: Test if the random number matches the persons own id and regenerate a new number if true.
do {
$assigned = rand(1,$maxpersons);
} while ($assigned==$id);
Step 3: Write the paired id to the persons database record.
$assignSQL = "UPDATE secretsanta SET assigned = '".$assigned."' WHERE secretsanta.id = ".$id;
if (mysqli_query($conn, $assignSQL)) {
echo "Record updated successfully";
} else {
echo "Error updating record: " . mysqli_error($conn);
}
The Problem: Now I need to check that other people aren't assigned to that person or otherwise some could miss out and others would get more than others.
I tried to implement a function that contained a query to test each record to see if that number already existed and was hoping to add it as a condition to perhaps a while or do while statement?
if (!function_exists('checkRandom')){
function checkRandom($funcid){
$Check_SQL = "SELECT assigned FROM secretsanta ORDER BY id ASC";
$Check_RES = mysqli_query($conn, $Check_SQL);
if (Check_RES) {
while ($CheckArray = mysqli_fetch_array($Check_RES, MYSQLI_ASSOC)) {
$CheckAsgn = $CheckArray['assigned'];
if ($funcid==$CheckAsgn) {return true;}else{return false;}
}
}
}
}
Then implement it into the do while statement like this:
do {
$assigned = rand(1,$maxpersons);
} while ($assigned==$id||checkRandom($assigned));
No luck so far...HELP!.. please :)
P.S. I know there are websites that already do this, I just don't trust them to give out mine and family email address' if I can make my own private version myself.
Using your method, the first few assignments will be done with no problem, but imagine the last unassigned entry and how many times it will try a random number only to find the person with that id is already assigned..
I'm gonna give you another approach to your problem: for each user that you want to assign a santa to, make a new SELECT statement with a WHERE clause that lets you select only those users that are not assigned yet.
check out my code and see if that helps you. I just typed this and didnt test it so there could be some mistakes.
// load all unassigned users into an array
$unassignedUsers = [];
$query = "SELECT id, assigned FROM secretsanta WHERE assigned is NULL";
$res = mysqli_query($conn, $query);
while($row = mysqli_fetch_assoc($res){
$unassignedUsers[] = $row;
}
if(count($unassignedUsers) == 1){
echo 'There is only 1 unassigned user. Therefore he cannot be matched';
} else {
// for loop for each user in DB that is not assigned yet
//for ($i = 1;$i <= count($unassignedUsers); $i++){
$i = 0;
foreach($unassignedUsers as $user)
// if its the second-to-last iterations of the for-loop, check for legality of the last one
if(count($unassignedUsers) - $i == 1){
$lastUserID = $unassignedUsers[count($unassignedUsers)-1]['id'];
$query = "SELECT id FROM secretsanta WHERE assigned is NULL AND id = ".$lastUserID;
$res = mysqli_query($conn, $query);
$rowcount = mysqli_num_rows($res);
if ($rowcount){
// last user is still unassigned
$query = "UPDATE secretsanta SET assigned = '".$lastUserID."' WHERE id = ".$user['id'];
if(mysqli_query($conn, $query)){
echo "Record with id ".$user['id']." updated successfully";
} else {
echo "Error updating record: ".mysqli_error($conn);
}
}
} else {
// select all unassigned users
$unassignedIDs = [];
$query = "SELECT id FROM secretsanta WHERE assigned is NULL AND id <> ".$user['id'];
$res = mysqli_query($conn, $query);
while($row = mysqli_fetch_assoc($res){
$unassignedIDs[] = $row['id'];
}
// get a random id from $unassignedIDs
$randomIndex = rand(0, count($unassignedIDs)-1);
$randomID = $unassignedIDs[$randomIndex];
// assign $randomID to user
$query = "UPDATE secretsanta SET assigned = '".$randomID."' WHERE id = ".$user['id'];
if(mysqli_query($conn, $query)){
echo "Record with id ".$user['id']." updated successfully";
} else {
echo "Error updating record: ".mysqli_error($conn);
}
}
$i++;
}
}
last edit: refactored whole code so it is able to be run multiple times and only assigns new users who are not assigned yet.
Step 1 is dependent on have a contiguous set of ids for the people. Think what happens if '3' leaves the company and it hires 6 to replace them....1,2,4,5,6 ($maxpersons=5)
"Now I need to check" - no you are still trying to solve the problem by guessing then seeing if your guess worked. Use an algorithm which is always going to return a correct result. The method below requires the addition of a temporary field 'sequence' of type float.
mysqli_query($conn,"UPDATE secretsanta SET sequence=RAND()");
$first=false;
$prev=false;
$all=mysqli_query($conn, "SELECT * FROM secretsanta ORDER BY sequence, id");
while ($r=mysqli_fetch_assoc($all)) {
if (false===$first) {
$first=$r['id'];
} else {
save_pair($prev, $r['id']);
}
$prev=$r['id'];
}
save_pair($prev, $first);
(but with better error checking)
I am building a car parking application in which different users have different numbers of parking spots. This number is set by an administrator in a database. The user can input a numberplate which then will be added to a database as well. What I want is that when a user has occupied all the spots, that he will not be able to insert any more number plates.
However, now I have the following code at the moment:
if(isset($_POST['number_plate'])){
$numberPlate = $_POST['number_plate'];
$user_id = $_SESSION['id'];
$query = mysql_query("SELECT `parking_spots` FROM `login` WHERE `id` = ".$user_id." ");
$row = mysql_fetch_assoc($query);
$totalNumberOfSpots = $row['parking_spots'];
$occupiedNumberOfSpots = 0;
$sql = "INSERT INTO amsterdam (numberplate, user_id) VALUES ('$numberPlate','$user_id')";
if(mysql_query($sql))
{
echo 'numberplate added';
$occupiedNumberOfSpots++;
if($occupiedNumberOfSpots == $totalNumberOfSpots)
{
echo "There are no more spots avialable";
}
}
else
{
echo 'Something went wrong!';
}
}
But when I echo the $occupiedNumberOfSpots variable it keeps returning 1 and does not increment every time I add numberplate.
How can I solve this issue?
It is because You are running the same code each time You add a plate to your db.
this:
$occupiedNumberOfSpots = 0;
should be taken from db as well. I guess it should be like that:
$totalNumberOfSpots = 100; // for example
$occupiedNumberOfSpots = $row['parking_spots']; // taken from db
instead of:
$totalNumberOfSpots = $row['parking_spots'];
$occupiedNumberOfSpots = 0;
The below script is called every 5 seconds. The issue is that if the server is responding slow, one entry in "blog" can get selected twice in a row because the server hasn't had time to set "done" to "1" yet. Is there an industry standard (or whatever you call it) way to prevent this from happening?
$result = mysql_query("SELECT * FROM blogs WHERE done=0 LIMIT 1");
$rows = mysql_num_rows($result); //If there are no entries in with done set to 0, that means we've done them all; reset all entries to 0.
if($rows == 0)
{
mysql_query("UPDATE blogs SET done=0 WHERE done=1");
}
else
{
while($row = mysql_fetch_array($result))
{
mysql_query("UPDATE blogs SET done=1 WHERE id=$row[id]");
// Do stuff
}
}
I think I could change it to
while($row = mysql_fetch_array($result))
{
if($row['done'] == 1){ die; }
mysql_query("UPDATE blogs SET done=1 WHERE id=$row[id]");
//Do stuff
}
But will that really fix the problem? I would imagine there would be a better way that really prevents it from happening without a shadow of a doubt.
I think the best way to prevent selecting the same row is using SELECT GET_LOCK("lock_name"); and SELECT RELEASE_LOCK("lock_name");. When you get a lock from mysql server, other processing trying to get a lock will wait for the lock to be released. Below is a sample implementation:
<?php
function getLock($lockName, $dbc) {
$query = "SELECT GET_LOCK('".$lockName."', 0)";
$result = mysql_query($query, $dbc);
$lockResult = mysql_fetch_row($result);
$lockResult = $lockResult[0];
return $lockResult == 1 ? true : false;
}
function releaseLock($lockName, $dbc) {
$query = "SELECT RELEASE_LOCK('".$lockName."')";
$result = mysql_query($query, $dbc);
}
// CONNECT TO DATABASE
$dbc = mysql_connect('localhost', 'root', '');
mysql_select_db('test', $dbc);
$loopQueue = true;
$rowsProcessed = 0;
// MAIN QUEUE LOOP
while ($loopQueue) {
// TRY UNTIL GETTING A LOCK
$queueLockName = 'queue_lock_1';
while (getLock($queueLockName, $dbc) === true) {
// WE GOT THE LOCK, GET A QUEUE ROW WITH PENDING STATUS
$query = 'SELECT * FROM test WHERE status = 0 ORDER BY ID ASC LIMIT 1';
$result = mysql_query($query, $dbc);
if (mysql_num_rows($result) < 1) {
// SINCE WE DON"T HAVE ANY QUEUE ROWS, RELEASE THE LOCK
releaseLock($queueLockName, $dbc);
// WE DONT NEED TO LOOP THE MAIN QUEUE ANYMORE SINCE WE DONT HAVE ANY QUEUE ROWS PENDING
$loopQueue = false;
// BREAK THIS LOOP
break;
}
// WE GOT THE QUEUE ROW, CONVERT IT TO ARRAY
$queueRowArray = mysql_fetch_assoc($result);
// UPDATE QUEUE ROW STATUS TO SENDING
$query = 'UPDATE test SET status = 1 WHERE id = '.$queueRowArray['id'];
mysql_query($query);
// RELEASE THE LOCK SO OTHER JOBS CAN GET QUEUE ROWS
releaseLock($queueLockName, $dbc);
// DO STUFF ...
// UPDATE QUEUE ROW STATUS TO PROCESSED
$query = 'UPDATE test SET status = 2 WHERE id = '.$queueRowArray['id'];
mysql_query($query);
$rowsProcessed++;
}
}
echo "\n\n".'process finished ('.$rowsProcessed.')'."\n\n";
I would have given a go to transactions. Here is an example in another StackOverflow question
Just a question: What happens if the server is even slower? For instance, the select statament takes so long (e.g. 5 seconds) that once it finishes (returning 0 rows), the new select is executed (returning 1 or more rows)
MySQL documentation
$result = mysql_query("SELECT * FROM blogs WHERE done=0 LIMIT 1");
$rows = mysql_num_rows($result); //If there are no entries in with done set to 0, that means we've done them all; reset all entries to 0.
if($rows == 0)
{
mysql_query("UPDATE blogs SET done=0 WHERE done=1");
}
else
{
while($row = mysql_fetch_array($result))
{
mysql_query("UPDATE blogs SET done=1 WHERE id=$row[id] AND done=0");
if(mysql_affected_rows() != 1)
die();
// Do stuff
}
}
I have a page that writes to a MySQL table. The table has a set amount of rows (24).
I have an $id variable that's set by a rand() function. I basically want to pull the row at that $id, so if $id was 3, I want to pull the third row. Then, I want to check if there is a price set at that row (indicating that the row is being used). If there is no price, I want to keep $id at the value it has been set at and proceed with the query. If there is a price, I want to re-randomize the $id variable, and check again if that row is used up. When it finds an empty row, proceed with the query.
My solution semi-works, but it seems to have a <10% chance of overwriting a used row, for some reason. I want it to never overwrite a used row.
Here's my code:
mysql_select_db("delives0_booklet", $con);
$query = "SELECT * FROM booklet WHERE id = '$id'";
$res = mysql_query($query,$con);
$newId = $id;
while($row = mysql_fetch_array($res))
{
if($row['price'] != 0)
{
do{
$newId = rand(1, 24);
}while($newId == $id);
}
}
$id = $newId;
mysql_query("UPDATE booklet SET price = '$price', advertiser = '$advertiser', image = '$image', monthsRemaining = '$monthsRemaining', availability = 1 WHERE id = '$id'");
Edit
I had the idea to do this. I loop through the table and I put the 'id' of each unfilled spot into an array. Then I pick randomly from that array. However, there seems to be a bug that I can't find, since the array keeps showing as having nothing in it, even after the loop is run, and $i is the correct figure.
mysql_select_db("delives0_booklet", $con);
$query = "SELECT * FROM booklet";
$res = mysql_query($query,$con);
$i = 0;
$isEmpty = array();
while($row = mysql_fetch_array($res))
{
if($row['price'] == 0)
{
$isEmpty[i] = $row['id'];
$i = $i + 1;
}
}
echo $i . " unfilled spots.";
$n = 0;
while($n<$i)
{
echo $isEmpty[$n];
$n = $n + 1;
}
if($i > 0)
{
$id = $isEmpty[rand(0, $i)];
}
if($i == 0)
{
echo 'All spots have been filled.';
}
I think it is a top level logic problem. Because you populate with random ids, you can get duplicate ids, and so when you update "WHERE id = '$id'" you may be picking up rows already populated.
I don't know your goal, but perhaps using an auto-increment id, and dropping rows that you want to get rid of, is the way to go. A rolling set of rows (24 at a time) but with ever increasing ids, would prevent mistaking one for the other.
If I understand the problem correct, this should work:
SELECT *
FROM booklet
WHERE price = 0 OR price IS NULL
ORDER BY RAND()
Alright let me explain myself here:
I am making an online text based game. I have a page where 3 things can happen:
They can create a position
Can edit a position
Can delete a position
So far I have creating a position working. I moved on deleting a position next. All was good and I got no errors, no warnings, etc.. And when I ran it, it came back to the screen it was supposed to after the script to delete the position ran. It is only supposed to come here after the query runs.
Well nothing happened and after 3 hours of trying crap I'm coming to you guys b/c I'm on my last leg. I still have no critical errors, nothing is making it fail: Here is my code.
<?php
//In the include file is the connection to the db
include("library/new_library.php");
//Below is the session id, gets their position id from the DB, than grabs whether or not they can edit the company
$user_id = $_SESSION['user_id'];
$sql = "SELECT ID, PositionID FROM users WHERE ID = '$user_id'";
$query = mysql_query($sql);
while($row = mysql_fetch_assoc($query))
{
$position = $row['PositionID'];
}
$sql = "SELECT * FROM tblCPositions WHERE PositionID = '$position'";
$query = mysql_query($sql);
while($row = mysql_fetch_assoc($query))
{
$editCompany = $row['Edit_Company'];
}
//Next I check for position edit and if they try to put in the position id of a position the company does not control it gives them a "nice" message.
$company = $_SESSION['company'];
if($_GET['pidedit']){
$position = $_GET['pidedit'];
$sql = "SELECT * FROM tblCPositions WHERE PositionID = '$position'";
$query = mysql_query($sql);
while($row = mysql_fetch_assoc($query))
{
if($row['CompanyID'] != $company)
{
$warning = "<div class='warning'>You are trying to edit a position that does not belong to your company. DO NOT TRY TO CHEAT THE SYSTEM!</div>";
}
else
{
$positionArray[] = array(ID => $row['PositionID'], name => $row['Name'], hire => $row['Hire'], fire => $row['Fire'], bid => $row['Contract'], edit => $row['Edit_Company'], finances => $row['Finances']);
}
}
}
//Here I check for $_GET delete
elseif($_GET['piddelete'])
{
$position = $_GET['piddelete'];
$sql = "SELECT * FROM tblCPositions WHERE PositionID = '$position'";
$query = mysql_query($sql);
while($row = mysql_fetch_assoc($query))
{
if($row['CompanyID'] != $company)
{
$warning = "<div class='warning'>You are trying to delete a position that does not belong to your company. DO NOT TRY TO CHEAT THE SYSTEM!</div>";
}
}
}
else
{
$sql = "SELECT * FROM tblCPositions WHERE CompanyID = '$company'";
$query = mysql_query($sql);
$number = mysql_num_rows($query);
$numberLeft = 12 - $number;
while($row = mysql_fetch_assoc($query))
{
$positionArray[] = array(ID => $row['PositionID'], name => $row['Name'], hire => $row['Hire'], fire => $row['Fire'], bid => $row['Contract'], edit => $row['Edit_Company'], finances => $row['Finances']);
}
}
//
if($_POST['submitNewPosition'])
{
$name = $_POST['positionName'];
$hire = $_POST['hire'];
$fire = $_POST['fire'];
$bid = $_POST['bid'];
$edit = $_POST['edit'];
$finances = $_POST['finances'];
$cid = $_SESSION['company'];
$sql = "INSERT INTO tblCPositions(CompanyID, Name, Hire, Fire, Contract, Edit_Company, Finances) VALUES ('$cid','$name','$hire','$fire','$bid','$edit','$finances')";
$query = mysql_query($sql);
if($query)
{
header("location: view_company.php?newp=success");
}
}
//Haven't finished this section yet
if($_POST['submitEditPosition'])
{
$name = $_POST['positionName'];
$fire = $_POST['hire'];
$fire = $_POST['fire'];
$bid = $_POST['bid'];
$edit = $_POST['edit'];
$finances = $_POST['finances'];
}
//This this is my problem area, this is where it says its running the query but its not.
if(isset($_POST['deletePosition']))
{
$deleteID = $_GET['piddelete'];
$deleteSql = "DELETE FROM tblCPositions WHERE PositionID = '$deleteID'";
$deleteQuery = mysql_query($deleteSql);
if($deleteQuery)
{
header("location: view_company.php?delete=success");
}
if(!$deleteQuery)
{
header("location: view_company.php?delete=failure");
}
}
UPDATE -
Ok so I got it working the problem was something I forgot, this form was just meant to be a "yes or no form" so I was doing post only to post the submit button, nothing else was on the form. What I had forgot was on the action="file.php" (what I had) I had forgotten to pass on the get variable so once I changed it to action="file.php?piddelete=12" it worked.
Thanks for everyones help I really appreciate it.
10 to 1 your variable $_GET['piddelete']; is empty. What do you get when you do this:
var_dump($_GET['piddelete']);
Disable the header redirect so that you can see the output.
edit
Or, as Nick pointed out, you can add die() statements to your queries:
$deleteQuery = mysql_query($deleteSql) or die(mysql_error());
If your query still runs, and the script doesn't die, and the position is still not deleted, you should check the query, it may be deleting 0 rows successfully. try killing at die($deleteSql); and run the query through MySQL's console.
/edit
Also, I'm compelled to introduce you to my good friend SQL injection attack. You should filter all data contained in the $_POST and $_GET superglobals before handing them over to the MySQL server. use mysql_real_escape_string().
Try to grok this:
whatever.com/your_url.php?pidedit=x'%3B%20DROP%20TABLE%20tblCPositions%3B%20--
If I were to execute that query string on your application, your tblCPositions table would be dropped.