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.)
Related
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.
I have a PHP script that helps me to make some financial reports like capital, profits, total sold item, total item in store between 2 dates:
$result[] = 0;
$res[] = 0;
$fetchStat[]=0;
if(isset($_POST['generate_capital']))
{
$from_d = $_POST['from_d'];
$to_d = $_POST['to_d'];
$stat = "SELECT sum(sell_quantity*(sell_price-init_price)) AS 'rebeh', sum(init_price*(quantity-sell_quantity)) AS 'capital', sum(sell_price*sell_quantity) AS 'profits', sum(quantity) AS 'total_item', sum(sell_quantity) AS 'total_sell' FROM purchases WHERE date_now BETWEEN :d1 AND :d2";
$stmtStat = $conn->prepare($stat);
$stmtStat->bindValue(':d1', $from_d);
$stmtStat->bindValue(':d2', $to_d);
$execStat = $stmtStat->execute();
$fetchStat= $stmtStat->fetchAll();
}
Now, the same query in MySQL workbench will give me a specific result:
SELECT sum(sell_quantity*(sell_price-init_price)) AS 'rebeh',
sum(init_price*(quantity-sell_quantity)) AS 'capital', sum(sell_price*sell_quantity) AS 'profits',
sum(quantity) AS 'total_item',
sum(sell_quantity) AS 'total_sell'
FROM purchases WHERE date_now BETWEEN '2016-02-02' AND '2016-05-09'
The result is:
And the same query in the PHP script with the same date range will give me other values:
I've changed the Arabic keywords with English ones so you can see the difference.
Any help is appreciated.
EDIT: Adding var_dump result for 2 dates
As it stands, it appears that the most likely cause is that your date formats have the month and day in the wrong order, for the 2nd of February, that doesn't matter, but for the 9th of May, it would become the 5th of September.
Now, the reason that the data for the 9th of May isn't included when you run the query directly is because a date is actually midnight on that date, making it exclusive of that date when it comes at the end of a between.
It's possible there is something else, so if this doesn't work, try echoing out all your values at every point, until you know exactly what is being run, and it should become clear.
To clarify, when using '/' in a date, MySQL uses the following format:
'%d/%m/%Y'
Which would explain why it works if you enter a string into your text box.
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
I am trying to code some manipulations that I need to perform on date format fetched from mySQL, the dates get fetched fine, having converted them TO_DAYS(), the problem is that any code after the line to fetch current date using TO_DAY(CURDATE()) does not get executed, and I cannot seem to understand why? Please Help my code is attached below:
//Final Date Calculation
$lastdate=mysql_query("SELECT TO_DAYS(date) FROM ordering WHERE id=1",$conn);
$num_rows_date = mysql_num_rows($lastdate);
while (($row_date = mysql_fetch_array($lastdate, MYSQL_ASSOC)) !== false){
$ldate[] = $row_date; // add the row in to the results (data) array
}
echo "Total number of records for the given id are: ",$num_rows_date, "<br />";
$ldatefinal=$ldate[$num_rows_date-1]['TO_DAYS(date)'];
echo "Last date in the records for the given ID is ",$ldatefinal,"<br />";
echo "Last date + Prediction days = ",$ldatefinal+$predict,"<br />";
$currentdate=mysql_query("SELECT TO_DAYS(CURDATE())",$conn);
$dcrow = mysql_fetch_assoc($currentdate);
//$dhold=$dcrow['TO_DAYS(CURDATE())'];
echo "Current Date is: ",$dcrow['TO_DAYS(CURDATE())'],"<br /" ;
//UPON EXECUTION NOTHING BELOW GETS ExEcuted ??
echo "Last date + Predicted days = ";
if(($ldatefinal+$predict)-$dcrow['TO_DAYS(CURDATE())'])<10){
echo "Time to Order<br />";
}else{
echo "You Got Gas!!";
}
mysql_close($conn);
In essence what this code is suppose to do is to get the delivery dates for a given id, than pick the last delivery date (I tried the LAST() function, but could not get it to work, I believe its for SQL SeRver), once the last delivery date has been determined (in days) it adds $predict value (the code for that is not included, but it is calculating and printing) after the addition of the two values the current date value is subtracted to see if according to a set trigger like say three days something like a push notification needs to be sent (also separate code), but in the code after correctly printing out the current date (echo line) nothing else gets executed, I have even tried putting dummy echo lines below that part to see if they would get printed, they dont!
It seems the following is the problem line in the code (I think)
echo "Current Date is: ",$dcrow['TO_DAYS(CURDATE())'],"<br /" ;
because every thing (including a simple echo test line does not get executed. Dont know why!
Please Help!
Hamood
Your if statement is not balanced with ( and ). The code is creating a parse error.
⬇︎ one more ( needed here
if((($ldatefinal+$predict)-$dcrow['TO_DAYS(CURDATE())'])<10){
How would I go about programming a daily message on my site that changes daily? I'm thinking of preloading all the messages in a MySQL database.
Any help would be appreciated!
Thanks,
I've tried
$msg_sql = "SELECT * FROM ".TABLE_PREFIX."quotes ORDER BY rand(curdate()) LIMIT 3";
$msg_res = mysqli_fetch_assoc(mysqli_query($link, $msg_sql));
But this only grabs the first MySQL result?
If you want a real message changing daily, you actually don't need to rely on a database or anything fancy. A simple idea might be to create a directory (say /var/www/motds) and populate it with files named YYYY-MM-DD.txt (where YYYY is a 4 digit year number, MM is a two digit month number and DD is a 2 digit day number).
Then, the only thing you need to do in order to display your motd is:
$filename = '/var/www/motds/'.date("Y-m-d").'.txt';
if (file_exists($filename)) {
echo file_get_contents($filename);
}
If you want your daily messages to be taken from a pool of entries (that you can pre-load), you might do something as follows:
$files = scandir('/var/www/motds'); // put files into an array
$messagecount = count($files) - 2; // .. and . shall not be considered
$day = date("z"); // what day do we have today?
echo file_get_contents('/var/www/motds/' . $files[($day % $messagecount) + 2]);
There are plenty of ways to get this done. You list PHP in your tags, so maybe check here:
PHP Script: Quote of the Day
or maybe here