my first time writing prepared statement
this code is checking your late in every 3 hours then inserting the time interval into db
date_default_timezone_set('Asia/Hong_Kong');
$now = new DateTime();
if ($now->format("H:i") > "22:00") {
$deadline = DateTime::createFromFormat("H:i", "22:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "19:00") {
$deadline = DateTime::createFromFormat("H:i", "19:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "16:00") {
$deadline = DateTime::createFromFormat("H:i", "16:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "13:00") {
$deadline = DateTime::createFromFormat("H:i", "13:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "10:00") {
$deadline = DateTime::createFromFormat("H:i", "10:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
} else if ($now->format("H:i") > "07:00") {
$deadline = DateTime::createFromFormat("H:i", "07:00");
$diff = $now->diff($deadline);
echo "You are ".$diff->h." hours and ".$diff->i." minutes late";
}
$stmt = $conn->prepare("INSERT INTO time_in (e_id, login, late, date_in)
VALUES (?, ?, ?,CURRENT_TIMESTAMP)");
$stmt->bind_param("sss", $e_id, $login, $diff->format('%H:%i'));
$e_id = "id is unavailable"; // changing to $_POST in the future
$login = "1";
$status = $stmt->execute();
if(!$status) {
echo $stmt->error;
exit;
}
echo "success";
}
and im getting this
Notice: Only variables should be passed by reference
at this line $stmt->bind_param("sss", $e_id, $login, $diff->format('%H:%i'))
the code working perfectly but im getting that notice
please help
you must pass actual variables to bind_param, since $diff->format('%H:%i') is not a variable but rather the output of a function, it doesn't like that.
You will need to assign this to a variable first then pass it in. i.e
$diffFormat = $diff->format('%H:%i');
$stmt->bind_param("sss", $e_id, $login, $diffFormat);
Related
<?php
function find_days($start_date, $end_date) {
$response = new stdClass();
try {
$sdate = new DateTime($start_date);
$edate = new DateTime($end_date);
$dateInterval = $edate->diff($sdate);
$response->status = true;
$response->result = $dateInterval;
return $response;
} catch (Exception $e) {
$response->status = false;
$response->result = 'Invalid Date Format';
return $response;
}
}
?>
Start Date: <input type="date" name="sdate" placeholder="start date" />
End Date: <input type="date" name="edate" placeholder="end date" />
<input type="submit" value="Find Days" />
<?php
if (isset($_POST['sdate']) && $_POST['sdate']) {
$start_date = $_POST['sdate'];
$end_date = $_POST['edate'];
//now call the function
$days_array = find_days($start_date, $end_date);
if ($days_array->status) {
echo " <input type='text' name='day'
value='.$days_array>result>days.' />";
$day = $_POST['day'];
$query = "INSERT into cart (date,edate,days)
VALUES('$start_date','$end_date','$day')";
$success = $conn->query($query);
if (!$success) {
die("Couldn't enter data: ".$conn->error);
}
} else {
echo $days_array->result;
}
}
My code is working perfectly. But the result is displayed only on the screen.
So I've tried to store the result by placing it in a textbox and then insert into the table in a usual way. But I got an error "Catchable fatal error: Object of class DateInterval could not be converted to string in C:\xampp\htdocs\date.php on line 45"
I don't know how to rectify this.. please help me solve this.
You have to convert it to a string using format:
<?php
$now = new DateTime();
$hour = new DateTime( "now +1hours +13minutes +22seconds" );
$diff = $now->diff( $hour );
echo $now->format('Y-m-d H:i:s');
echo "\n";
echo $hour->format('Y-m-d H:i:s');
echo "\n";
echo $diff->format('%H:%I:%S');
Output
2018-07-26 20:53:42
2018-07-26 22:07:04
01:13:22
I am trying to prevent a user from cancelling a booking if the booking is less than 2 days away. I tried doing this by getting the current date and the date of the booking, converting them both to strtotime and then checking if one value was greater than the other. However when I run my code though all it does is redirect to page which only displays the value of $diff
Here is my code
<?php
$customerRef = $_SESSION['customerRef'];
$messageCancelError;
$messageSuccess;
if (isset($_POST['Cancel']))
{
if ($_SERVER['REQUEST_METHOD'] == 'POST')
{
$cancelAppointment = $_POST['cancel'];
//echo $cancelAppointment;
$sql4 = "SELECT dateOfBooking FROM booking WHERE bookingRef=? AND customerRef=?";
// initalise the prepared statement
$stmt4 = mysqli_stmt_init($conn);
// prepare the prepared statement
if (mysqli_stmt_prepare($stmt4, $sql4))
{
// bind values to the prepared statement
mysqli_stmt_bind_param($stmt4, "ss", $cancelAppointment, $customerRef);
// execute the prepared statement
mysqli_stmt_execute($stmt4);
// store the results of the prepared statement
mysqli_stmt_store_result($stmt4);
// bind the results of the prepared statement to variables
mysqli_stmt_bind_result($stmt4, $appointmentDate);
mysqli_stmt_fetch($stmt4);
//echo mysqli_stmt_error($stmt4);
//gets the current date in y-m-d format
$date = date('Y-m-d'); //gets the difference in todays date and the date of an appointment in seconds
$diff = abs(strtotime($date) - strtotime($appointmentDate)); echo $diff;
}
$stmt4->close();
}
$stmt4->close();
//172800 seconds in 2 days
if ($diff > 172800)
{
// checking for customer ref as well to prevent a user cancelling another users booking
$sql3 = "DELETE FROM booking WHERE bookingRef =? AND customerRef =?";
$stmt3 = mysqli_stmt_init($conn);
if (mysqli_stmt_prepare($stmt3, $sql3))
{
mysqli_stmt_bind_param($stmt3, "si", $cancelAppointment, $customerRef);
mysqli_stmt_execute($stmt3);
mysqli_stmt_store_result($stmt3);
// echo mysqli_stmt_error($stmt3);
}
if (mysqli_stmt_affected_rows($stmt3) === 1)
{
$messageSuccess = "Booking Cancelled";
}
else
{
$messageCancelError = "Couldn't cancel your booking, check your booking ref against existing ones ";
}
}
// Close statement
$stmt3->close();
// Close connection
// $conn->close();
}
I have tried changing it to this but the error is still happening
if ($diff > 172800) {
// checking for customer ref as well to prevent a user cancelling another users booking
$sql3 = "DELETE FROM booking WHERE bookingRef =? AND customerRef =?";
$stmt3 = mysqli_stmt_init($conn);
if (mysqli_stmt_prepare($stmt3, $sql3)) {
mysqli_stmt_bind_param($stmt3, "si", $cancelAppointment, $customerRef);
mysqli_stmt_execute($stmt3);
mysqli_stmt_store_result($stmt3);
// echo mysqli_stmt_error($stmt3);
if (mysqli_stmt_affected_rows($stmt3) === 1) {
$messageSuccess = "Booking Cancelled";
}//affected rows
}//stmt_prepare
}//$diff
else {
$messageCancelError = "Couldn't cancel your booking, check your booking ref against existing ones ";
}
Your if block needs to change.
Change:
//172800 seconds in 2 days
if ($diff > 172800)
{
...
if (mysqli_stmt_affected_rows($stmt3) === 1)
{
$messageSuccess = "Booking Cancelled";
}
else
{
$messageCancelError = "Couldn't cancel your booking, check your booking ref against existing ones ";
}
}
// Close statement
To:
//172800 seconds in 2 days
if ($diff > 172800)
{
...
if (mysqli_stmt_affected_rows($stmt3) === 1)
{
$messageSuccess = "Booking Cancelled";
}
}
else
{
$messageCancelError = "Couldn't cancel your booking, check your booking ref against existing ones ";
}
// Close statement
I want to block a someone who tried to login 4 times with a wrong password.
The problem is: When I use "modify" and change the timestamp with 15 minutes, I get -1 as output and after two minutes I get -2 as output. I tied for so long and I searched a lot on internet, but it still doesn't work.
How I want it to work:
In the database is the column: "falselog". If the username of the visiter is correct but the password is incorrect, falselog will be +1. When falselog is 4, the visiter will be banned for 15 minutes. So the visiter is able to try 4 times. After 15 minutes, the visiter can try again.
This is my object with all the code:
public function logUser($username, $password) {
// query id = 2
$sql2_1 = "SELECT
id,
password,
falselog,
lastlogin
FROM users
WHERE username ='".$username."' ";
$result2_1 = $this->con->query($sql2_1);
$fetch2_1 = mysqli_fetch_array($result2_1);
$count2_1 = $result2_1->num_rows;
$now = new DateTime('now');
$blockedSince = new DateTime($fetch2_1['lastlogin']);
$fout = $fetch2_1['falselog'];
$date_old = date ("Y-m-d H:i:s", strtotime("now"));
$block = date("i", $fetch2_1['lastlogin']) + 16;
$current = date("i", strtotime("now"));
$wait = $block - $current ;
$dbtime = date ("Y-m-d H:i:s", strtotime($date_old));
// This is the code that doesn't work
if ($fetch2_1['falselog']>=4 AND $blockedSince->modify('+15 minutes') > $now) {
$error[] = 'This account has been banned, try again about '.$wait.' minutes';
$decline = true;
$date_old = $fetch2_1['lastlogin'];
}
elseif (!preg_match("/^[A-Za-z0-9-]+$/", $username)) {
$error[] = 'De input bevat ongeldige tekens (alleen cijfers en letters toegestaan)';
}
elseif ($count2_1 === 0) {
$error[] = 'Wrong login data';
}
elseif ($fetch2_1['password']!=sha1($password)) {
$error[] = 'wrong password';
$fout = $fetch2_1['falselog']+1;
}
if ((count($error) == 0) OR ($fetch2_1['falselog']==4 AND $blockedSince->modify('+15 minutes') < $now)) {
$fout = 0;
}
$sql2_2 = "UPDATE users SET
falselog='".$fout."',
lastlogin='".$dbtime."'
WHERE username='".$username."' ";
if ($this->con->query($sql2_2) === TRUE) {
if (count($error) == 0) {
return false;
}
else {
return $error;
}
}
else {
echo "Error: " . $sql2_2 . "<br>" . $this->con->error;
return true;
}
}
You should check that here
$blockedSince = new DateTime($fetch2_1['lastlogin']);
you get the correct data for DateTime, try var_dump($blockedSince); after this line, and check that it has correct value inside;
try this
$blockedSince = mktime($fetch2_1['lastlogin']);
I am using a simple script at the top of every page that will update a LastActive column in the database:
$username = $_SESSION['username'];
$userID = $_SESSION['user_id'];
if(isset($username, $userID)) {
if ($insert_stmt = $mysqli->prepare("UPDATE Users SET lastActive = DATE_ADD(Now(), interval 6 hour) WHERE username = ?")) {
$insert_stmt->bind_param('s', $username);
// Execute the prepared query.
if (! $insert_stmt->execute()) {
$insert_stmt->close();
header('Location: ../headers/error.php?err=Failed Upload');
}
}
$insert_stmt->close();
}
I always want to keep performance and security in mind. Would this lead to poor performance in the future with 000's of connections?
How does using cookies (not that I know how) differ from a simple script like this?
Thanks
edit:
$username = $_SESSION['username'];
$userID = $_SESSION['user_id'];
$loginTime = $_SESSION['timestamp'];
date_default_timezone_set("Europe/London");
$now = new DateTime();
$diff=$now->diff($loginTime);
$minutes = $diff->format(%i);
if(isset($username, $userID) && $minutes> 30) {
$_SESSION['timestamp'] = $now;
$online = true;
}
Couple of suggestions:
You could do this via AJAX, so that the LastVisited is updated asynchronously after the user's page loads. That way, there won't be any impact to the page load time for the user.
If, for any reason, your SQL query fails, you should fail silently. Since recording Last Visited is not business critical, you should not redirect the user to an error page. Maybe just log an error, and set up an alert so if there are multiple failures, you get alerted and can take a look at it.
All that you made with cookies will be data supplied by your users, then you cannot trust it.
In other hand, if you work with cookies, all of them will travel in each request header.
You should do it in server side and yes, a database is not performant.
You can try to persist this information with something like Redis, a in-memory data structure store, used as database, cache and message broker.
I thought I'd post the way I got around this for any one else looking for a User Online type method. Of course this might have been done much better but works in my situation.
I am using both database entries and session to test if a user is online.
On user login I update a column in my users table with a Now() timestamp and add this to their session data.
At the top of each page I am running a script to check if the user is logged in and get their timestamp from session data. if this data is 45 minutes old, the script will update the table setting the lastActive column of my users table to Now();
<?php
include_once 'functions.php';
if(isset($_SESSION['username'], $_SESSION['user_id'], $_SESSION['lastActive'])) {
date_default_timezone_set("Europe/London");
$now = new DateTime();
$lastActive = $_SESSION['lastActive'];
$diff=$now->diff($lastActive);
$hours = $diff->format('%h');
$mins = $diff->format('%i');
$day = $diff->format('%d');
$month = $diff->format('%m');
$year = $diff->format('%y');
if($mins > 45 || $hours >= 1 || $day >= 1 || $month >= 1 || $year >= 1) {
$_SESSION['lastActive'] = $now;
set_last_active($mysqli, $_SESSION['username']);
}
}
set_latst_action is simply just:
function set_last_active($mysqli, $username) {
if ($stmt = $mysqli->prepare("UPDATE Users SET lastActive = Now() WHERE username = ?")) {
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->close();
}
}
then when I want to see if a user is online for example on a profile page I call isOnline();
function isOnline($mysqli, $username) {
if ($stmt = $mysqli->prepare("SELECT lastActive FROM Users WHERE username = ? LIMIT 1")) {
$stmt->bind_param('s', $username);
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows == 1) {
$stmt->bind_result($return);
$stmt->fetch();
$lastActive = $return;
} else {
// user does not exist
$lastActive = "";
return $lastActive;
$stmt->close();
}
} else {
// SELECT failed
$lastActive = "";
return $lastActive;
$stmt->close();
}
if (!empty($lastActive)) {
date_default_timezone_set("Europe/London");
$dateNow = new DateTime;
$lastActiveDate = new DateTime($lastActive);
$diff=$dateNow->diff($lastActiveDate);
$hours = $diff->format('%h');
$mins = $diff->format('%i');
$day = $diff->format('%d');
$month = $diff->format('%m');
$year = $diff->format('%y');
if ($mins > 45 || $hours >= 1 || $days >= 1 || $month >= 1 || $year >= 1) {
$return = "Offline";
return $return;
}
else {
$return = "Online";
return $return;
}
}
else {
$return = "Offline";
return $return;
}
}
I am making the booking script for rent a car. User will enter two dates at the time of booking, start date and end date, what i need that it checks that the entered dates are between the dates that are already stored in the Db for that specific car,
In simple words, if car is booked from 2015-23-08 to 2015-25-08, and user entered the dates between these two its shows an error other wise the order should be placed.
Issue in code: it always shows me "in between" even i entered different values
Code:
include 'connection.php';
if (isset($_GET['id'])) {
// escape variables for security
$fleettype = $_POST['fleettype'];
$fleetname = $_POST['fleetname'];
$fleetclass = $_POST['fleetclass'];
$fleetdescription = $_POST['fleetdescription'];
$fleetprice = $_POST['fleetprice'];
$username = $_POST['username'];
$useremail = $_POST['useremail'];
$userphone = $_POST['userphone'];
$sdate = $_POST['sdate'];
$edate = $_POST['edate'];
$time = $_POST['time'];
$driver = $_POST['driver'];
$useremail = $_POST['useremail'];
$id = preg_replace('#[^0-9]#i', '', $_GET['id']);
$products = mysqli_query($con, "SELECT * FROM fleet WHERE id='$id' LIMIT 1 ");
while ($row = mysqli_fetch_assoc($products))
{
$stime = $row["stime"];
$etime = $row["etime"];
}
$entereddate = DateTime::createFromFormat('Y/m/d', $stime);
$contractDateBegin = DateTime::createFromFormat('Y/m/d', $sdate);
$contractDateEnd = DateTime::createFromFormat('Y/m/d', $edate);
if ($entereddate >= $contractDateBegin && $entereddate <= $contractDateEnd)
{
echo "in between";
}
else {
echo "no";
}
}
You dont need to wrap the date in single quotes if the date is help in a variable, so change your `createFromFormat statements like so.
Also the else has to have an echo "no" where you just had a "no"
$entereddate = DateTime::createFromFormat('Y/m/d', $stime);
$contractDateBegin = DateTime::createFromFormat('Y/m/d', $sdate);
$contractDateEnd = DateTime::createFromFormat('Y/m/d', $edate);
if ($entereddate >= $contractDateBegin &&
$entereddate <= $contractDateEnd)
{
echo "in between";
} else {
echo "no";
}
You might get better results doing this as I am pretty sure you cannot compare DateTime objects like that.
$entereddate = strtotime($stime);
$contractDateBegin = strtotime($sdate);
$contractDateEnd = strtotime($edate);
if ($entereddate >= $contractDateBegin &&
$entereddate <= $contractDateEnd)
{
echo "in between";
} else {
echo "no";
}
You can't put single quotes around variables, or it won't interpolate them:
$entereddate = DateTime::createFromFormat('Y/m/d', '$stime');
$contractDateBegin = DateTime::createFromFormat('Y/m/d', '$sdate');
$contractDateEnd = DateTime::createFromFormat('Y/m/d', '$edate');
should just be:
$entereddate = DateTime::createFromFormat('Y/m/d', $stime);
$contractDateBegin = DateTime::createFromFormat('Y/m/d', $sdate);
$contractDateEnd = DateTime::createFromFormat('Y/m/d', $edate);
What is happening is, none of the "dates" you entered are valid - it is seeing if the string $stime - which could just as easily be the string banana, is a date. It is not. So $entereddate is set to false. As is $contractDateBegin, and $contractDateEnd.
So then, it checks if false >= false && false <= false, which it is (false == false). So it will always echo "in between";
http://sandbox.onlinephpfunctions.com/code/0cb5b5fc82598708fdff66d013d041467bb6fd8a