PHP/mySQL get time difference by x seconds - php

My goal is to get the time difference between 2 different times, one from my database, and one from the client's PHP timestamp, and compare them. Then, if the time difference is less than or equal to 10 seconds, then do something.
My code, which does not work, is as follows.
date_default_timezone_set('America/Chicago');
$timestamp = date('Y-m-d H:i:s');
$sqlcheck = $dbh->prepare("SELECT timestem FROM mytable WHERE UNIX_TIMESTAMP(timestem) - UNIX_TIMESTAMP('".$timestamp."') <= 10");
$sqlcheck->execute();
if ($sqlcheck === ''){
echo "Yes";
}
else {
echo "No";
}
timestem is a DATETIME value from mySQL. $sqlcheck is meant to portray the result of the query. If the query returns nothing, then echo Yes. If it returns something from my query, then echo No.
Without getting too convoluted in explanation, my end-goal is to check how long it has been since a database operation before a client is allowed to perform updates.

You should use the MySQL built-in TIMESTAMPDIFF function:
$sqlcheck = $dbh->prepare('SELECT timestem FROM mytable WHERE TIMESTAMPDIFF(SECOND, timestem, $1) <= 10');
$result = $sqlcheck->execute([$timestamp]);
Note that instead of concatenating strings, I am providing the $timestamp as a parameterized argument.
To check the result, you can't just check for string equality. Instead, use fetchColumn on the result object:
if ($timestem = $result->fetchColumn()) {
echo "YES";
// You can also use the value of `$timestem` here.
} else {
echo "NO";
}
Note that this assumes there is only one row. For multiple rows, you need a loop. Note that only rows that match the condition are returned, so you will never see any NO output if you use a loop.

You can just as easily do the check in PHP (which will probably be a bit more straight-forward)
$sqlcheck = $dbh->prepare( "SELECT timestem FROM mytable" );
$sqlcheck->execute();
// You missed this step
$timestem = $sqlcheck->fetchColumn();
if ( time() - strtotime( $timestem ) > 10 )
print 'yes';
else
print 'no';
Some notes:
In your code you didn't actually get the value out of the database. You used the result object in your conditional
Your code implicitly assumes there is only ever one record in your table. This probably isn't true: you will need a where condition
You have to be very certain that all of your timestamps are in the same time zone
This will only work if you are using PDO, not mysqli. I can't tell the difference from your example, but a subtle difference is that PDO will allow you to use a prepare and execute with no bound parameters, but mysqli won't.

Related

PHP PDO sqlsrv large result set inconsistency

I am using PDO to execute a query for which I am expecting ~500K results. This is my query:
SELECT Email FROM mytable WHERE flag = 1
When I run the query in Microsoft SQL Server management Studio I consistently get 544838 results. I wanted to write a small script in PHP that would fetch these results for me. My original implementation used fetchAll(), but this was exhausting the memory available to php, so I decided to fetch the results one at a time like so:
$q = <<<QUERY
SELECT Email FROM mytable WHERE flag = 1
QUERY;
$stmt = $conn->prepare($q);
$stmt->execute();
$c = 0;
while ($email = $stmt->fetch()[0]) {
echo $email." $c\n";
$c++;
}
but each time I run the query, I get a different number of results! Typical results are:
445664
445836
445979
The number of results seems to be short 100K +/- 200 ish. Any help would be greatly appreciated.
fetch() method fetches one row at a time from current result set. $stmt->fetch()[0] is the first column of the current row.
Your sql query has no ordering and can have some null or empty values (probably).
Since you are controlling this column value in while loop, if the current row's first value is null, it will exit from the loop.
Therefore, you should control only fetch(), not fetch()[0] or something like that.
Also, inside the while loop, use sqlsrv_get_field() to access the columns by index.
$c = 0;
while ($stmt->fetch()) { // You may want to control errors
$email = sqlsrv_get_field($stmt, 0); // get first column value
// $email can be false on errors
echo $email . " $c\n";
$c++;
}
sqlsrv_fetch

Comparison between a timestamp in MYSQL table with a PHP variable NOT Working - PHP MYSQL

I'm trying to filter out repeated values entering into a MySQL table, by comparing the input PHP variable with the timestamp of an entry already present in the table and only if they don't match, the input PHP variable is entered into the table.
$user1_date = mysql_real_escape_string($user1_date); // the date variable
$user1_temp1 = mysql_real_escape_string($user1_temp1);
$user1_temp2 = mysql_real_escape_string($user1_temp2);
$user1_temp3 = mysql_real_escape_string($user1_temp3);
$user1_date = date("Y-m-d H:i:s", strtotime($user1_date)); //Typecasting PHP variable into timestamp
$sql_check = "SELECT * FROM user_details WHERE temp_date ='$user1_date'";
$result_check = mysql_query($sql_check);
$num_rows_check = mysql_num_rows($result_check);
if ($num_rows_check == 0) // To check if there is no entry in the table with the same date and time as input PHP variable
{
$sql_insert = "INSERT INTO data_hour (user_id, temp1, temp_date, temp2, temp3)
VALUES (1,'$user1_temp1', '$user1_date', '$user1_temp2', '$user1_temp3')";
$result_insert = mysql_query($sql_insert);
}
temp_date is a column in the table of type timestamp. Even when the $user1_date is the same as the temp_date(timestamp) column for one of the entries in the table, it considers it as not equal and is inserting it into the table and hence I'm getting repeated values. I'm guessing the WHERE temp_date = '$user1_date'is not working properly. Some troubleshooting that I have done included
Changing '$user1_date' to just $user1_date in the WHERE
statement
Changing the WHERE clause as follows WHERE temp_date = (date)'$user1_date'
It will be great if somebody can help me out with this!
A nice easy solution would be giving temp_date a UNIQUE INDEX in your Mysql Table, as that would not allow the same value to be inserted twice. This would also make your operations more efficient, as you wouldn't have to do SELECT * every time you want to insert something.
However, for what you're doing, I think I see your problem; there are some quirks in your logic so I'll try to dispel them here. (Hopefully?) this will make your program cleaner and you'll be able to pinpoint the error, if not eliminate it altogether.
Examining this piece of code:
// $user1_date doesn't have a value here! //
$user1_date = mysql_real_escape_string($user1_date);
...
$user1_date = date("Y-m-d H:i:s", strtotime($user1_date));
Error 1 - You escape the string before ever setting a value.
What you are doing is that you are using mysql_real_escape_string() before $user1_date is ever defined.
Correction:
// Getting better, but not done. //
$user1_date = date("Y-m-d H:i:s", strtotime($user1_date));
...
$user1_date = mysql_real_escape_string($user1_date);
Error 2 - You do not give the date() function appropriate parameters
The date() function in PHP expects a timestamp, which is just an int. You can easily get the time with time(), so that should rectify your problem
Correction:
// You use strtotime($user1_date), but you should use time() //
$user1_date = date("Y-m-d H:i:s", time());
...
$user1_date = mysql_real_escape_string($user1_date);
These are small mistakes, but they can be deadly. Like I said, you should assign temp_date to a UNIQUE INDEX in your MySQL table, but make sure to correct these errors listed as well.
Let me know how it goes!

MySQL - Compare all values in a column and write in another column

I need to create a script that compares one field in the database (has a date stored, it's type is "TEXT" and cannot be changed DATE) to the current server date.
The dates are encoded like this "1380571547", so i need to use strftime() to decode them. This field for example, decoded with strftime corresponds to this "Sep-30-2013, 22:05"
What I need is to compare those fields with the current date, and according to that condition, write something like "Expired" in another field.
To achieve this, I made this block of code:
<?php
require("connection.php");
$today = strftime('%b-%d-%Y, %H:%M');
$exp_date = mysql_query("SELECT numbers FROM date");
while($row = mysql_fetch_array($exp_date))
{
echo (strftime ( '%b-%d-%Y, %H:%M', $row ['numbers'])). "<br />";
}
if ($exp_date < $today) {
$sql = "INSERT INTO date (changed) VALUES ('EXPIRED')";
$result = mysql_query($sql);
echo "ADDED!";
}
?>
However, this code is not working, can someone help me ?
PHP is not my strong point but it looks to me like you condition is doing a comparison on an array,
IE:
if ($exp_date < $today) // will always be false.
Your code would probably have to look something more like this.
while($row = mysql_fetch_array($exp_date))
{
if ($row[0] < $today)
{
$sql = "Update date set changed = VALUE where rowid = rowid";
$result = mysql_query($sql);
echo "ADDED!";
}
}
having said that i would probably do the comparison and update in SQL using a case statement,
Update Date
set changed = case when number > ExpiryDate
then "Expired"
else "Current"
end
You can do all this in a single query:
UPDATE `date` set `changed`='Expired' where date(now()) > date(from_unixtime(`numbers`))
But this is not what your code is attempting to do. Your second block seems to be inserting the word Expired in new rows, rather than updating anything.
Note that the table name date should be wrapped in backticks to avoid any possible clash with MySQL keywords
I don't understand the second block of code with the insert. I would do an update inside the loop. but if your going to do that, it could probably be done in one combined update statement.

MySQL INSERTing rows into a database with datetime sanity checks

I am making a meeting room booking system in which there should be no times within the start and end dates so in theory the validation should check for no dates/times within one start and end date time frame.
I have two tables, I can insert into it fine with both start and end dates so the only columns i am interested in at the moment are these
meetingrooms
|------------------------------------||- bookingtime -|-bookingend-|
I understand the principle behind the sanity check and the check i can do in psudocode. Here is the code i have got so far -
>
p4a_db::singleton()->query("INSERT INTO meetingrooms(location_id, bookingtime, bookingend, merono_id)
WHERE bookingtime < " . $date . " AND bookingend > " . $date . "
OR
bookingdate < " . $date . " AND bookingend > " . $dateend . "
VALUES(?,?,?,?)",
array($location, $date, $dateend, $merono));
I don't want to insert data directly into the statement but until i understand how to do this i am stuck, so the question,
How do i perform a sanity check before the data is inserted so that i don't get dates within booked times.
any help would be greatly appreciated.
Edit:
I've been overthinking my answer and I realized that the old solution will not work in your case since you need the time span, comparing the start and end date is useless.
My way of processing this would be:
Save the dates as int, use 24h system (7:40am is 740, 9:50pm is 2150)
Check for stored dates where: (Start<NewStart<End)
Check for stored dates where: (Start<NewEnd<End)
When processing several rooms, just store room number + time as int. That way you can still use the method from 2 and 3.
2 and 3 can be done in a sql query, check out this link.
Old answer (checking for duplicates)
This is an example of how to check for duplicates (in this case email) before inserting the text:
$emailexist = $mysqli->prepare("select email from users where email = ?");
$emailexist->bind_param('s', $email);
$emailexist->execute();
$emailexist->store_result();
if ($emailexist->num_rows > 0) {
$emailexist->close();
$mysqli->close();
return true;
}
else {
$emailexist->close();
$mysqli->close();
return false;
}
It checks if there are rows which contain the string. If so (if number of rows higher than 0) it returns true (which means, the date already exists).
You can just adapt this to you code.
However, you could also just set the columns to UNIQUE. Then you get an error when trying to insert it. It is easier and you won't have problems with concurrent connections.
after a long and intensive search, I have now got a working example of this method, along with a method of protecting against sql injection, here's the code;
if ($this->BookingValue == 1)
{
$sql = "SELECT COUNT(*) as num FROM meeting_room_bookings
WHERE
(
(? < start_at AND ? > start_at)
OR
(? > start_at AND ? < end_at)
)
AND
meeting_room_id = ?";
$result = p4a_db::singleton()->fetchRow($sql, array($date, $date, $date, $dateend, $merono));
if ( 0 == $result["num"] )
{
p4a_db::singleton()->query("INSERT INTO meeting_room_bookings (start_at, end_at, meeting_room_id)
VALUES
(?,?,?)", array($date, $dateend, $merono));
return true;
}
else
{
return false;
There isn't much to explain about this code, but in term of differences, (excluding the change in column names with the table) the query is now prepared before the value is set, then it is possible to use it in an if statement, thus allowing the validation to take place to filter results between different dates.
along with this i have added validation to stop dates from other meeting rooms being included within the statement via the AND statement where the meeting room id is limeted to a single value.
Although now, which will lead on to a separate question is another thrown error that comes from this statement, i know the insert is sound but something from this prepared statement causes the error:
SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens
File: Pdo.php, Line: 234
Although now i am looking into a error that is thrown from the prepared statement and will update this answer when there is a fix, thanks for the help.

Function query won't execute

Why won't this query work?!?
Error
Parse error: syntax error, unexpected T_STRING in E:\xampp\htdocs\pf\shop\buy.php on line 5
Example Info For Variables
$character->islots = 20
$chatacter->name = [RE] Tizzle
$e2 = 10
The Function
function increaseSlots($e2) {
$slots = ($character->islots)+($e2);
mysql_query('UPDATE `phaos_characters` SET `inventory_slots`="'.$slots.'" WHERE `name`="'.$character->name.'"'); // <-- Line 5
if (mysql_affected_rows() != 0) {
echo 'Inventory Size Incresed By '.$e2.' Slots';
}else{
echo mysql_error();
}
}
Look at the docs: http://php.net/manual/en/function.mysql-num-rows.php
Retrieves the number of rows from a result set. This command is only valid for statements like SELECT or SHOW that return an actual result set. To retrieve the number of rows affected by a INSERT, UPDATE, REPLACE or DELETE query, use mysql_affected_rows().
You need to use mysql_affected_rows() or better yet, PDO or mysqli.
$slots = ($character->islots)+($e2);
Looks like there is a typo. Try:
$slots = ($character->slots)+($e2);
First off you should know that mysql_num_rows only returns a valid result for SELECT or SHOW statements, as stated in the PHP documentation. You can use mysql_affected_rows() for your particular needs.
However, the old PHP MySQL API (that you are using) is being phased out, so I would recommend using mysqli or PDO for your DB connection needs.
While keeping with your requirements, though, you can try to use the following syntax to make sure you receive the MySQL error if it throws one. Your PHP script will stop, but you will see the error.
$query = sprintf('UPDATE `phaos_characters` SET `inventory_slots`=%d WHERE `name`="%s"',$slots,$character->name)
$result = mysql_query($query) or die(mysql_error());
As a final idea, in situations like this it helps to print out your resulting $query and run it manually through something like phpMyAdmin to see what happens.
Bleh... I Found a better way to do it for the time being.. sorry to waste your guys' time...
I just threw the $character object into a variable before processing the function.
function increaseSlots($e2,$charname,$charslots) {
$slots = $charslots+$e2;
mysql_query('UPDATE `phaos_characters` SET `inventory_slots`="'.$slots.'" WHERE `name`="'.$charname.'"');
if (mysql_affected_rows() != 0) {
echo 'Inventory Size Incresed By '.$e2.' Slots';
}
}

Categories