【问题标题】:Delete database row after a set expiry time (e.g. 5 minutes)在设定的到期时间(例如 5 分钟)后删除数据库行
【发布时间】:2016-05-09 20:51:11
【问题描述】:

背景:我正在设计一个在线虚拟教室管理系统...它的工作原理是在教师创建教室时生成随机会话密钥(md5(时间))并将其存储在数据库中.

为了访问教室,学生访问唯一的教室 url,代码将 url 中的会话密钥(使用 GET)与数据库中的会话密钥进行比较。如果匹配,则显示教室。

网址通常如下所示:/classroom.php?instance=a529501db8373609f2d47a7843a461ea

需要编码帮助:我希望我的老师也能够设置会话“长度”,以便教室可以访问 15 分钟、25 分钟或 50 分钟。

如果自创建教室以来的时间超过例如 25 分钟,则会话密钥将从数据库中删除,并且无法再访问教室。

我目前所拥有的:

当老师点击按钮创建课堂时,下面的 PHP 会将会话密钥 ($instance) 和会话长度 ($duration) 存储在数据库中...

<?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();
}
?>

然后在实际的教室.php 页面上,一个 sn-p 代码检查会话是否已过期...如果是,则将其从数据库中删除。

<?php 

$currentTime = time();

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

任何帮助或建议将不胜感激!

更新----

感谢所有出色的答案,这就是目前一切的运作方式......

在 createclassroom.php 页面上,我将实例以及 NOW() 日期和时间以及持续时间存储为 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();
}
?>

在实际的classic.php 页面上,我只检查未过期的会话实例。

<?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');
}
?>

现在我只需要决定如何经常清除数据库。真的,我要感谢你们的帮助,正是我所需要的!

【问题讨论】:

  • 为什么不给老师一个 close room 按钮,将 db 中的值设置为 false,因此无法访问?最好保留诸如此类的内容以供不满意的学生等进行审查/反馈。
  • 这是我见过的最快的反应,好主意!将不得不考虑我将如何实施该想法以及它是否确实解决了我所有的问题。谢谢。
  • 您需要在数据库中存储课程可用的时刻(开始时间和日期)和持续时间。这样,您可以将持续时间添加到开始并计算当用户尝试登录时课程是否关闭
  • 尝试查看 jQuery AJAX 向脚本发送请求,该脚本会在某种事件上为您执行此操作,例如单击按钮。希望你一切顺利':P

标签: php mysql session


【解决方案1】:

假设你的桌子看起来像这样:

  CREATE TABLE IF NOT EXISTS sessions (
      classroom_id int(10) unsigned NOT NULL AUTO_INCREMENT,
      session_key varchar(60) NOT NULL,
      duration tinyint(3) unsigned NOT NULL,
      created timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
      PRIMARY KEY (classroom_id)
 ) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

你的持续时间总是以秒为单位,你可以通过这样的查询来实现你想要的:

SELECT  classroom_id
FROM    sessions
WHERE   session_key = :key
AND     (UNIX_TIMESTAMP(created) + (duration * 60)) > UNIX_TIMESTAMP(NOW());

【讨论】:

    【解决方案2】:

    将expiry DATETIME 添加到教室表中,并在创建它时设置它的到期时间。

    在课堂页面中,只需将到期时间与当前时间进行比较。

    奖励:如果人们在过期后不尝试访问教室,您的数据库可能会变大。您可以创建一个 cronjob 偶尔删除过期的教室:DELETE FROM classroom WHERE expiry &lt; NOW()

    【讨论】:

      【解决方案3】:

      这种行过期通常是这样处理的:

      1. 将过期时间DATETIME 放在每一行中。 INSERT INTO tbl (id, expiration) VALUES (whatever, NOW() + INTERVAL 5 MINUTE)
      2. 查找行时,在查询中使用AND tbl.expiration &gt; NOW() 之类的内容。这将使过期的行看起来消失了。
      3. 在方便时,可能在通宵工作或每小时 EVENT 中,删除过期行:DELETE FROM tbl WHERE tbl.expiration &lt;= NOW()

      这比在到期时尝试实际DELETE 到期的行要容易得多,而且时间精确得多。它还可以抵御立即 DELETE 操作的失败,并且可以很好地扩展。

      【讨论】:

      • 使用INTERVAL 路由的问题是您不能使用列值动态设置数字,因此需要带有有限数量选项的CASE 语句,或者更改php 查询字符串中的值,这可能需要额外的查询才能首先查找到期分钟值...
      • 我不确定这是否是一个大问题?我只需要 3 个值,看来我可以通过编写 INSERT INTO dbname.instances (instance, expiry) VALUES ('$instance', NOW() + $duration);
      猜你喜欢
      • 1970-01-01
      • 2020-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-18
      • 2023-03-07
      • 2019-12-07
      相关资源
      最近更新 更多