0

我是 PHP/SQL 新手用户....完成我的第一个 PHP 网站。该问题类似于在以下位置找到的初始问题:

http://forums.phpfreaks.com/topic/266235-modifying-database-after-a-set-time-limit/

但我并没有完全理解答案。与该用户类似,我有一整列(称为status)的数据库(称为challenge),它可以采用 3 个状态值- 'inactive'、'pending' 或 'active'。在正常的网站操作流程中,用户 A 通常会单击一个按钮(事件 1),该按钮会在数据库中创建一个新行(具有唯一的 *challenge_id*)并在该行中触发“待定”状态。用户 B 可以通过其他点击按钮更改状态,可以将状态设置为“非活动”或“活动”。

一种不受欢迎的情况是用户 B 什么都不做(即,没有事件触发)。在这种情况下,用户 A 不幸卡住了,等待状态从“待定”变为“活动”或“非活动”,然后他/她才能单击并触发下一个事件 1。例如,如果用户 B 厌倦了该站点并且不再使用它,则可能会发生这种情况,从而使“待处理”请求未得到答复。

显然,我可以手动更改 SQL,在一定时间限制后将任何“待定”状态更改为“非活动”。这在开始时会很好,但如果该网站变得流行,这将需要更多时间。有没有办法编写一个非 PHP 程序来解决这种“无事件触发”场景,其中所有“待定”状态 SQL 条目在一定时间限制后自动更改?或者PHP可以做到这一点吗?我尝试编写一个 php 脚本,每次任何用户登录时都会扫描数据库(注意:*challenge_id* 是由在不同 PHP 页面上触发的事件创建的):

<?php session_start();

if ((($_SESSION['role']) != SHA1('user')) && (($_SESSION['status']) != SHA1('active')))     
{
header( 'Location: index.php' ) ;
session_destroy();
} else 


include 'connect.php';

$_SESSION['login_id'];

$universaltime = time();

$sqlt = mysql_fetch_assoc(mysql_query("SELECT challenge.challengetime, 
challenge.status FROM challenge"); //Selects an array of all values for challengetime 
//and status for all users I presume


while ((($universaltime - $sqlt['challengetime']) > 1000) && 
($sqlt['status'] == 'pending'))   
{

$sqlt1 = mysqli_query("UPDATE challenge SET $sqlt['status'] ='inactive'"); 
//Also tried with if instead of while

}



?>

我确信我的代码可以改进......任何帮助将不胜感激!还是我需要使用 PHP 以外的东西?

4

2 回答 2

2

首先你的UPDATE说法是错误的。假设它challengetime是包含 unix 时间值的 int 数据类型,您的 UPDATE 语句应该看起来像这样

UPDATE challenge 
   SET status = 'inactive'
 WHERE status = 'pending' 
   AND 1000 < UNIX_TIMESTAMP() - challengetime;

它可以并且应该独立运行。您无需在调用之前选择任何内容。因此你可以改变这部分

$universaltime = time();
$sqlt = mysql_fetch_assoc(mysql_query("SELECT challenge.challengetime, 
challenge.status FROM challenge"); //Selects an array of all values for challengetime 
//and status for all users I presume
while ((($universaltime - $sqlt['challengetime']) > 1000) && 
($sqlt['status'] == 'pending'))   
{
$sqlt1 = mysqli_query("UPDATE challenge SET $sqlt['status'] ='inactive'"); 
//Also tried with if instead of while
}

只需

$sql = "UPDATE challenge SET status = 'inactive' WHERE status = 'pending' AND 1000 < UNIX_TIMESTAMP() - challengetime";
$result = mysql_query($sql);
if (!$result) {
    die('Invalid query: ' . mysql_error()); //TODO better error handling
}

现在要让它自己定期执行,你不一定需要 php.ini。你可以:

第一个选项使用MySQL 事件。每天晚上 11 点执行这个语句

CREATE EVENT change_status
ON SCHEDULE EVERY 1 DAY 
   STARTS CURDATE() + INTERVAL 23 HOUR 
DO 
  UPDATE challenge 
     SET status = 'inactive'
   WHERE status = 'pending' 
     AND 1000 < UNIX_TIMESTAMP() - challengetime;

用于SHOW PROCESSLIST检查是否启用了事件调度程序。如果它打开,您应该看到Daemon用户“ ”的进程“ event_scheduler”。SET GLOBAL event_scheduler = ON;如果当前未启用,则用于启用调度程序。有关在此处配置事件调度程序的更多信息

第二个选项使用 crontab 调用 CLImysql

/usr/local/mysql/bin/mysql -uuser -ppassword -e " UPDATE challenge SET status = 'inactive' WHERE status = 'pending' AND 1000 < UNIX_TIMESTAMP() - challengetime"
于 2013-09-02T05:37:56.740 回答
0

如果您的 Web 和 PHP 服务器在 Linux 上运行(通常是这种情况)并且延迟x超过几分钟(即x>=5 分钟),那么您可以使用crontab(1)并添加一个crontab(5 )条目。请记住在那里使用绝对路径。该条目将(定期)运行一些脚本(您可以使用 PHP 编写代码,也可以使用 Python 或 OCaml 等其他脚本语言编写),这些脚本将更新 MySQL 数据库。

于 2013-09-02T05:07:06.883 回答