I am providing 24 hours trial membership in my android application. I do not know more about PHP. I want check user registration time and want disable trial membership if 24 hours got passed. I have made little PHP file for that.
$sql = "SELECT id, email, registration_time FROM user WHERE trial = 1";
$result = $conn->query($sql);
if($result) {
while($row = $result->fetch_row()) {
$id = $row[0];
$email = $row[1];
$registrationTime = strtotime($row[2]);
$currentTime = strtotime("-1 day");
if($currentTime > $registrationTime) {
$update = "UPDATE user SET trial = 0 WHERE email = '$email'";
$conn->query($update);
$update = "UPDATE number_list SET disable = 1 WHERE user_id = $id";
$conn->query($update);
}
}
}
Its not providing any result even I have one user which time passed more than 48 hours.
How can I solve this issue?
try this and check
$currentTime=date('m-d-Y',strtotime($registrationTime . "-1 days"))
You should use a prepared statement to update the database for all the users with the same email (your first update query). Also see the documentation.
If someone registers with an e-mail address like test'; DROP ALL TABLES; --#gmail.com1 this code will dutifully remove your database. Never put user data into code directly like that.
Now let's look at the example code;
$sql = "SELECT id, email, registration_time FROM user WHERE trial = 1";
$result = $conn->query($sql);
if($result) {
while($row = $result->fetch_row()) {
You're saying there is no result at all. I assume that you've tested the output with a debug statement. E.g. putting echo 'users exist'; in between here. The first thing to do would be to check your user table if there are any rows. Does this SQL query produce results?
Assuming that it does, there doesn't appear to be anything wrong with the SQL statement. Assuming you have a table called user with four columns id, email, registration_time, and trial it should produce results.
Next, what you want to do is read the query function documentation. As you can see there, when a query fails, for whatever reason, it returns FALSE. Try writing an 'else' code block and logging the error that occurs. You can fetch it using the error function mysqli::error. Try appending this code;
} else {
echo "MySQL Error: " . $conn->error;
}
Where you can replace the echo with your error handling of choice.
It's probably a good idea to write a wrapper for mysqli if you're going to execute more than a few queries in your application. That way, you can write error handlers in your wrapper class for what your application should do if a query or database connection fails.
What could also be the case is that, while your initial query succeeds and fetches some rows, the time check fails. You may want to do some stricter date/time parsing than using strtotime and hoping for the best. Assuming you're using a TIMESTAMP column to store the data, you can use this:
function readDatabaseTimestampValue($value) {
$dateTime = date_create_from_format("Y-m-d H:i:s", $value);
$timestamp = $dateTime->getTimestamp();
return $timestamp;
}
Check the exact time data returned from your database. Dates and times are complicated, and if things are reinterpreted, say the day number in SQL may become the year in the PHP app, which can cause strange bugs. E.g. you can do this by doing say:
echo "24 hours ago: " . strtotime("-1 day") . ", user data: " . $row[2];
Next, you probably have some bugs in the logic. '24 hours ago' is better done by doing this, as using '-1 day' will cause weird issues when people mess with the calendar:
$timestamp = time() - 86400;
There's 86,400 seconds in a day (well, excluding DST and leap seconds, but you want 24 hours of subscription time, not 23 hours around the 21st of March).
Finally, there's problems if the same E-mail address is present more than once in the table. You will set 'trial' to 0 for one user, but may set the 'disable' flag for another if two users register within the same 24-hour period with the same e-mail. If the latter is guaranteed to be unique then this is no issue. Otherwise, you may want to update by id in both tables.
Next, we can look at some optimization. Right now, you fetch everything from the database. But you can do much better/faster by having an index on registrationTime, and using the database's sorting features. E.g. let's say we know the exact date/time of 24 hours ago as $yesterday in PHP we can write a query like:
SELECT id, email, registration_time FROM user WHERE trial = 1 AND registration_time > ?
Bind the $yesterday variable to the parameter. Now you no longer need the if() statement; the database does it for you. Also, as your database grows, you're not checking the old records one-by-one every time the code runs.
1Note, that may not be a legal e-mail address, but there's probably ways to do evil things even with a legal mail address.
Related
I have a simple update query for when someone subscribes to my web app, updating the details of their license.
Recently I made some minor changes to this and it has stopped working (I presume these are linked, but haven't actually managed to prove this) - I've tried reversing whatever I did but seems to be to no avail.
For some reason, the update runs successfully and all fields update, except the expiry field.
I write my sql query into a log file and I've copied this into phpmyadmin command line and it works exactly as expected.
[Result is:
UPDATE License
SET type='Full'
, payer_id = 'XXXXXXX'
, gross = 'XXXX'
, payer_email = 'XXXXXXX'
, license_start = '2019-08-21 14:46:17'
, expiry = '2019-09-21'
, product = 'MON'
, stripe_id = 'XXXXXX'
WHERE user_id = XXX
which seems fine to me
I've adapted the format, apostrophes, I've even just put a date in like '2019-12-10' and it still won't update via the mysqli query. I've also tried expiry = $start, which requires truncation, but should work... still just doesn't update that field.
$expiry = date("Y-m-d", strtotime("+$couponmonths months", strtotime(date("Y-m-d H:i:s",$expiryts))));
$start = date ("Y-m-d H:i:s");
$sql = "UPDATE `$license_table` SET `type`='Full', `payer_id`='$subid', `gross`='$price', `payer_email`='$email', `license_start`='$start', `expiry` = '$expiry', `product`='$product_name', `stripe_id`='$stripeid' WHERE `user_id`=$userid";
}
...
if (mysqli_query($connection,$sql) === TRUE) {...}
Thanks those of you that tried to help. I've fixed this now by literally creating a new column called expiry_date instead of expiry, copying the data across to the new column, and updating all references.
Feel like I haven't solved what went wrong, but I have at least got it working again. It felt like the column had decided to to accept updates via PHP - not sure this is even possible???
I decided to try this course of action when I sent a query saying only to update this column and it still didn't work... madness!
Would love to hear an explanation if there is one, but just happy to have it working for now.
I think you should be setting $expiry, which presumably gets inserted into a datetime or timestamp type column in your DB, with the default SQL datetime format Y-m-d H:i:s as you did below.
Also, make sure that
strtotime("+$couponmonths months", strtotime(date("Y-m-d H:i:s", $expiryts)))
actually works the way you intend and returns the desired time.
Also, you should use {} to insert variables into strings.
Like so:
"UPDATE `{$license_table}` SET `type`='Full', `payer_id`='{$subid}', `gross`='{$price}', `payer_email`='{$email}', `license_start`='{$start}', `expiry` = '{$expiry}', [...]"
and so on.
This makes sure php is interpreting the variables correctly.
If all still fails, try to dump the query string and run it manually with the DB-manager or cli of your choice, for you to debug.
I am trying to convert three separate database columns into a date (day,month,year) and calculate the age so only users over the age of 15 or 18 can purchase certain products. The code below doesnt work as it echoes '0 days, 0 months, 0 years' and still adds the product to the basket. Which means the age calculation doesnt work, and my first if statement doesnt work either.
<?php
$username = $_SESSION['solentuser'];
echo "$username's account!<br>";
$conn = new PDO("mysql:host=localhost;dbname=u;","u","p");
$productID= htmlentities($_GET['ID']);
//startdate
$result=$conn->prepare("SELECT * FROM users WHERE username=:username");
$result->bindParam(":username",$username);
$result->execute();
$row=$result->fetch();
$birthdate = $row['yearofbirth'] . $row['monthofbirth'] . $row['dayofbirth'];
$presentdate = date('Ymd');
$birthday = new DateTime($birthdate);
$currentdate = new DateTime($presentdate);
$age = $birthday->diff($currentdate);
echo $age->format('<br>%d Days %m Months %y Years<br>');
//enddate
$results=$conn->prepare("SELECT * FROM products where ID=:productID");
$results->bindParam(":productID",$productID);
$results->execute();
$row=$results->fetch();
if($row['agelimit'] <= $age){
if($row['stocklevel'] >= 1){
$result=$conn->prepare("INSERT INTO basket(productID,username,qty) values(:productID,:username,1)");
$result->bindParam(":productID",$productID);
$result->bindParam(":username",$username);
$result->execute();
$result=$conn->prepare("UPDATE products SET stocklevel=stocklevel-1 WHERE ID=:productID");
$result->bindParam(":productID",$productID);
$result->execute();
echo "You have successfully added this product to your basket!";
}
else{
echo "This product is out of stock!";
}
}
else{
echo "You are not old enough to purchase this product!";
}
//print_r($conn->errorInfo());
?>
any suggestions as to where the error is? i have read that it is possible to write an if statement inside an if statement, so why does this one not work?
thank you!
I'd echo out $birthdate and verify there's a valid date there. (We aren't getting back single digits, a date of 2009-05-04 getting represented as '2009', '5' and '4' such that when we concatenate them, we get 200954, or maybe extra spaces. (We're not seeing the datatypes of the three separate columns.)
We might try adding some delimiters in there, so we'd get 2009-5-4, likely we could get that converted into a DateTime, using the correct format string.
If I had separate values for month, day and year, I would use PHP mktime, and then create a DateTime object from that.
(MySQL does provide a DATE datatype that allows for a very large range of valid dates, and doesn't allow invalid dates to be stored. Storing three separate columns to represent a single date just smells like the wrong way to do it. (If I actually needed the separate month and day columns (to allow indexing for some queries), I would add those in addition to the birthdate DATE column, not in place of it, with triggers to keep the values in sync with the birthdate column.)
Also, $age is a DateInterval object. You seem to be aware that we can use the format method to extract integer number of years.
$age_yrs = $age->format('%y');
We're guessing that the database column age_limit is integer years.
if( $row['agelimit'] <= $age_yrs ) {
Right before that if statement, we can confirm that what we think to be true is actually true...
echo " age_yrs=" . $age_yrs;
echo " row_age_limit=" . $row['age_limit'];
Looking closely at the debugging output helps us identify if the problem is before the if statement or after, so we aren't chasing down a problem in a section of code where there isn't a problem, the problem is somewhere else, on a preceding line.
I encourage you to develop the skills needed to debug programs that you write. It seems like you are making some (wrong) assumptions about what the variables are containing.
Adding echo and var_dump during development is a first step in verifying that what you think to be true is actually true.
I'd go as far as recommending that you look at every line of code you write as possibly going wrong, especially in edge cases.
https://ericlippert.com/2014/03/05/how-to-debug-small-programs/
(StackOverflow is a question/answer community, not a debugging service.)
Trying to make a little Search feature for a user, so he can type in a date on a webpage made with HTML/PHP, and see which people in the db have registered as member on or after (a date). My user inputs the date in format 2015-10-01. This gets sent to a PHP page with a jqxGrid on it, populated with member details of members conforming to my query on the MySQL database (using PDO).
The query uses the operator >= on a string passed as (for example) "2015-10-01" in the WHERE clause, so I am using STR_TO_DATE to make the comparison work:
WHERE `lastUpdated` >= STR_TO_DATE( ? , '%Y-%m-%d');
With PDO, the ? later gets bound to the date (which was passed in as a string).
The db column for registration date is in DATETIME format, and in the db values look like: "2015-10-12 17:12:52".
My query returns an empty array every time, - and this after many hours of trying every conceivable permutation of date format, both in the MySQL statement and on the page that prepares the data for populating the grid.
Can someone show me what's wrong here?
Thanks!!
SP
Make it
WHERE `lastUpdated` > ?
and check your data and stuff.
Basically, you should never touch PDO until you get raw SQL to work.
okay, so here is the PDO version that works - passing in ? instead of the date:
function getJSONAllMembersByDate($PDOdbObject, $regDate)
{
try
{
$membersByDateSQL = "SELECT `id`, `name_first`, `name_last`, `organization`,`email`, `phone`,`source`,`comments`,`language_id`, `lastUpdated` FROM `member` WHERE lastUpdated>=?";//'$regDate'
$get=$PDOdbObject->prepare($membersByDateSQL);
$get->execute(array($regDate));
$rows = $get->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($rows);
return $json;
}
The fact that it works proves there were other errors in the file containing the jqxwidget (the version before I posted here). I certainly tried about a million different things to get this working.
I don't know if this counts as an answer, but at least it WORKS! There are so many variables in this problem - json, jqxgrid, pdo ... not forgetting that there are several ways to use PDO. I probably had several errors in different places.
(#apokryfos, the STR_TO_DATE was indeed unnecessary.)
In the end, this is what works:
In the PHP page containing the jqxGrid, the url sent to the server is:
url: 'my-json-responses.php?fct=getJSONAllMembersByDate®Date=<?php echo $fromDate ?>'
This $fromDate comes from the $_POST when the user typed in a date (in the format 2015-10-01) on the input page. When the PHP page containing the jqxGrid loads, it does
$fromDate = $_POST['regDate'];
The url "transits" through the file my-json-reponses.php, which contains many functions. It finds the right one:
if ($_GET['fct'] == 'getJSONAllMembersByDate')
{
$result = getJSONAllMembersByDate($connectionObject, $_GET['regDate']);
echo $result;
}
The $result is called on the file that contains all my PDO database requests, including:
function getJSONAllMembersByDate($PDOdbObject, $regDate) { try
{
$membersByDateSQL = "SELECT `id`, `name_first`, `name_last`, `organization`,`email`, `phone`,`source`,`comments`,`language_id`, `lastUpdated` FROM `member` WHERE lastUpdated>='$regDate'";
$get=$PDOdbObject->query($membersByDateSQL);
$rows = $get->fetchAll(PDO::FETCH_ASSOC);
$json=json_encode($rows);
return $json;
}
catch (PDOException $e)
{
echo "There was a problem getting all members with this search query.";
echo $e->getMessage();
}}
Note that I couldn't make the version using "?" in the query work at all, hence passing in the variable $regDate directly, with single quotes around the variable just to make life interesting.
This returns a nice list of all my users as of 2015-10-01 - but is presumably still open to MySQL injection attacks ...
But after this marathon of debugging I am happy enough for now. (All improvements welcomed, naturally!)
SP
hello all i am trying to find the recent birthday of the registered members on the site and also store the result of query into session so that next time the query need not to be executed so to reduce the page load time and also server load
i am having this code
if(!isset($_SESSION['dob']) || $_SESSION['dob'] =='' ){
$frndlist=$_SESSION['friendlist']; //comma seperated list of friends
$CurrMOnth= date('m'); // this month
$BirthDLAST0n=date('d', strtotime(' - 7 day'));
$BirthDGRATEn=date('d', strtotime(' + 7 day'));
$GEttheBIrthdaYS=mysqli_query($connection,"select id,name,dob from members
where (id IN ($frndlist)) and (MONTH(dob) = '$CurrMOnth') and
(DAY(dob) > '$BirthDLAST0n' and DAY(dob) < '$BirthDGRATEn' )
order by dob desc limit 10");
$_SESSION['dob']=$GEttheBIrthdaYS;}else{
$GEttheBIrthdaYS=$_SESSION['dob'];
}
while($theBdaYSreYAr90=mysqli_fetch_array($GEttheBIrthdaYS)){ //print }
but the problem here is result of query is stored into session but it is never accepted by the mysqli_fetch_array it says error.
this is problem because i am trying to store object onto session
is there any alternative to store the result into something so that the same query need not to be executed gain again ....
and also the birthday script is not good it dosent displays the birthday of people whose DOB is at the last or begning of months.
please let me know how to store the result of query into session or cookie
as cookie stores very less size i dont think cookie is good option.
Looks like you're trying to put a whole array into the session var, just break it up.
$result = mysql_fetch_array($GettheBIrthdaYS);
$_SESSION['dob'] = $result['dob'];
Also make your limit 1, unless you want more than 1 record, which if you do then you will need to change everything.
So I'm trying to block voting for 24hours after a user has already voted, and I've been stuck for a while now. I tried working off this earlier post but I haven't had any luck. I was able to echo the ip address but not the vote_time
I have a database with a table named voterlist that has two columns: submission_ip and vote_time. (the time is formatted like this date("Y-m-d H:i:s",time()) )
My php looks like this:
<?php
$ip = mysql_real_escape_string($_SERVER['REMOTE_ADDR']);
$query = "SELECT vote_time FROM voterlist WHERE submission_ip ='$ip'";
$result = mysql_query($query);
if(mysql_num_rows($result) < date('Y-m-d H:i:s',strtotime('-24 hour'))) {
echo 'you can vote again in 24 hours';
}else {
echo 'vote now';
}
?>
Any help with this query would be greatly appreciated.
In your line
if(mysql_num_rows($result) < date('Y-m-d H:i:s',strtotime('-24 hour'))) {
What are you trying to do here exactly?
The first term, mysql_num_rows($result) is the amount of rows the query returned. The second term, date('Y-m-d H:i:s',strtotime('-24 hour')) is some date string, like 2015-01-25 22:47:00. You're comparing them, why?
Instead, check for the date in the query:
SELECT vote_time FROM voterlist WHERE submission_ip ='$ip' AND `vote_time` > timestampadd(day, -1, now())
Then, if mysql_num_rows($result) gives you 1 or more, that means there is a record, so there has been a vote in the last 24 hours. If the number of rows is 0, there has not been a vote in the last 24 hours.
Besides that, blocking by IP is a bad idea. Do you want to block a whole company after one employee has voted? You could use authentication with some OpenID provider to ensure people only vote once, however, privacy may be an issue. If you have a list of the people who are allowed to vote (and it's not 'everyone') you could look into systems as RIES, which was used in some elections in the Netherlands a few years ago. (In 2008 the software was released and shown to have extensive security problems.)
Also note that the mysql_* functions have been deprecated (docs) in favour of PDO_MySQL and mysqli_*.