Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete database row after a set expiry time (e.g. 5 minutes)

Tags:

php

mysql

session

Background: I am designing an online virtual classroom management system... it works by generating a random session key (md5(time)) when a teacher creates a classroom and storing it in a database.

To gain access to the classroom the student visits the unique classroom url and the code compares the session key in the url (using GET) to the session key in the database. If there is a match then the classroom displays.

URLs typically look like this: /classroom.php?instance=a529501db8373609f2d47a7843a461ea

Coding help needed: I want my teachers to also be able to set a session 'length', so the classroom is accessible for either 15 minutes, 25 minutes or 50 minutes.

enter image description here

When the time since the classroom was created exceeds for example 25 minutes then the session key is deleted from the database and the classroom can't be accessed any more.

What I have so far:

When a teacher clicks the button to create a classroo the PHP below stores the session key ($instance) and the session length ($duration) in the database...

<?php
session_start();
if (isset($_SESSION['id'])) {
    if (isset($_POST['hidden'])) {

        // Connects to the database
        include_once("$_SERVER[DOCUMENT_ROOT]/classes/includes/dbconnect.php");
        mysql_connect(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);

        // Sets the session duration
        $currentTime = time();
        $duration = $currentTime + $_POST['duration'];

        // Session variables
        $uid = $_SESSION['id'];
        $usname = $_SESSION['username'];

        // To generate the random hash from the current time
        $time = time(); // time to hash
        $instance = md5($time); // hash stored in variable

        // Stores the session hash (instance) and duration in the instance database
        $query = ("INSERT INTO `my-db-name-foo`.`instances` (`instance`, `expiry`) VALUES (`$instance`, $duration`);");
        mysql_query($query) or die(mysql_error());

        // Closes the database connection
        mysql_close();

        // Redirects the teacher header('Location:classroom.php?instance='.$instance);
    } 
} else {
    echo 'Please login';
    die();
}
?>

Then on the actual classroom.php page a snippet of code checks to see if the session is expired... if it is it deletes it from the database.

<?php 

$currentTime = time();

if ($currentTime > $duration){
    // Connect to database and delete the row
} else {
    // show the classroom
}
?>

Any help or suggestions would be greatly appreciated!

UPDATE ----

Thanks for all the great answers, here is how it all is working at the moment...

On the createclassroom.php page I am storing the instance as well as the NOW() date and time AND the duration as NOW() + $_POST['duration'];...

<?php
session_start();
if (isset($_SESSION['id'])) {
    if (isset($_POST['duration']) && !EMPTY($_POST['duration'])) {

        // Connects to the database
        include_once("$_SERVER[DOCUMENT_ROOT]/classes/includes/dbconnect.php");

        // Session variables
        $uid = $_SESSION['id'];
        $usname = $_SESSION['username'];

        // To generate the random hash from the current time
        $time = time(); // time to hash
        $instance = md5($time); // hash stored in variable

        // $duration = $_POST['duration'];
        $duration = $_POST['duration'];

        // Stores the hash (instance) in the instance database
        $sql = ("INSERT INTO `xxx_xxxx`.`instances` (`id`, `teacher`, `instance`, `startdate`, `expiredate`) VALUES ('$uid', '$usname', '$instance', NOW(), NOW() + $duration);");
        $query = mysqli_query($dbConnect, $sql)or die(mysql_error());

        // Redirects the teacher        
        header('Location:classroom.php?instance='.$instance);
    }  else if (isset($_POST['hidden'])) {
        echo 'Please select a duration';
    }
} else {
    echo 'Please login';
    die();
}
?>

On the actual classroom.php page I am only checking session instances that are not expired.

<?php 
session_start();

// Connects to the database
include_once("$_SERVER[DOCUMENT_ROOT]/classes/includes/dbconnect.php");

$instance = $_GET['instance']; // GETs instance from URL
$usname = $_SESSION['username']; // Gets teacher name

// script to retrieve all the Instances in the database and store them in a variable '$dbInstance'
$sql = "SELECT instance, expiredate FROM instances WHERE instance = '$instance' AND instances.expiredate > NOW()";
$query = mysqli_query($dbConnect, $sql);
$row = mysqli_fetch_row($query);

$dbInstance = $row[0];

if ($dbInstance == $instance){
    echo $dbInstance.'<br>';
    echo $instance;
} else {
    echo $dbInstance.'<br>';
    echo $instance.'<br>';
    die('Instance not initiated');
}
?>

Now I just need to decide how I want to clear the database every so often. Really, I want to thank you guys for the help, just what I needed!

like image 846
Jethro Hazelhurst Avatar asked Feb 07 '23 21:02

Jethro Hazelhurst


2 Answers

This sort of row expiration is usually handled as follows:

  1. put the expiration DATETIME in each row. INSERT INTO tbl (id, expiration) VALUES (whatever, NOW() + INTERVAL 5 MINUTE)
  2. when looking up rows, use something like AND tbl.expiration > NOW() in the query. That will make the expired rows appear to be gone.
  3. When convenient, perhaps on an overnight job or an hourly EVENT, get rid of the expired rows: DELETE FROM tbl WHERE tbl.expiration <= NOW()

This is much easier and far more time-precise than trying to actually DELETE expired rows right at the moment they expire. It's also resilient against failures of the immediate DELETE operations, and it scales up nicely.

like image 168
O. Jones Avatar answered Feb 10 '23 09:02

O. Jones


Add expiry DATETIME to the classroom table, and when you create it set the time when it'll expire.

In the classroom page just compare expiry with the current time.

Bonus: your DB might get big if people don't try to access the classrooms after expiry. You can make a cronjob that deleted expired classrooms once in a while: DELETE FROM classroom WHERE expiry < NOW()

like image 39
Gavriel Avatar answered Feb 10 '23 11:02

Gavriel