[PHP]详谈可控制的定时器(附源码)

一、引言

恰逢公司的项目需要用到定时器,在网上搜了许多的资料,虽说PHP本身是无状态的语言,用来做定时器非常的麻烦和耗资源,但是实际应用上还是少不了的。方法有几个:

1,利用计算机系统本身的计划任务

2,利用js前台刷新页面定时访问PHP文件

3,利用PHP死循环长连接

由于1,2两种办法都没办法很好地对定时器进行很好的控制,而本篇主要讲的是可控制的定时器,因此我们来详看第三种方法。

二、思路

思路其实不复杂,利用 while(true)死循环让PHP脚本一直处于执行的状态。但是!要注意的是,PHP本身是有一个机制会中断无响应的脚本的,因此,我们要加上。

1
2
ignore_user_abort(false);//当用户关闭页面时服务停止
set_time_limit(0);  //设置执行时间,单位是秒。0表示不限制。

先给出一个基本的范式,其中有个人的测试程序:

1
2
3
4
5
6
7
8
9
10
11
<?php
ignore_user_abort(); // run script. in background
set_time_limit(0); // run script. forever
$interval=30; // do every 15 minutes...
do{
$fp = fopen('text3.txt','a');
fwrite($fp,'test');
fclose($fp);
sleep($interval); // wait 15 minutes
}while(true);
?>

首先运行该程序,然后关闭该页面,程序仍然运行中,test会每隔30秒的填补到text3.txt文件。

至此一个简单的定时器算是OK了,但是它是不可控制的,因为程序处于死循环中,是无法接受外界的数据的。

那么我们要实现可控制,怎么办呢?解决办法是有的,这里很多种办法,比如读数据库,读文件,我带来的方法也简单,就是用PHP本身的INCLUDE,这样效率也不会太低,消耗的资源也不会太过于大!

即:在死循环中,加一个 if();,判断的条件,就是 $flag = include ‘路径/配置文件.php’;

而这个 [配置文件.php] 的内容很简单,就一句:<?php return true; ?>;

当你需要这个定时器停下来的时候,用文件函数fopen打开这个配置文件,然后替换true为false就可以了,这就是基本的思路!

三、源码例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?php

ignore_user_abort (); // 即使Client断开(如关掉浏览器),PHP脚本也可以继续执行.
set_time_limit ( 0 ); // 执行时间为无限制,php默认的执行时间是30秒,通过set_time_limit(0)可以让程序无限制的执行下去

class money extends admin {

public $timer_switch; //定时器-开关-文件
public $timer_h; //定时器-时-文件
public $timer_m; //定时器-分-文件
public $timer_delay; //定时器-间隔时间(秒)-文件
public $timer_value; //利息利率

public function __construct(){
parent::__construct();
$this->;db = System::load_sys_class("model");
$this->;timer_switch = dirname(__FILE__)."\\timer_switch.php";
$this->;timer_h = dirname(__FILE__)."\\timer_h.php";
$this->;timer_m = dirname(__FILE__)."\\timer_m.php";
$this->;timer_delay = dirname(__FILE__)."\\timer_delay.php";
$this->;timer_value = dirname(__FILE__)."\\timer_value.php";
}

public function index(){
if(isset($_POST['submit'])){
$this->;h($_POST['h']);
$this->;m($_POST['m']);
$this->;delay($_POST['delay']);
$this->;value($_POST['value']);
$msg = '【保存成功】';
}
$switch = include $this->;timer_switch;
$h = include $this->;timer_h;
$m = include $this->;timer_m;
$delay = include $this->;timer_delay;
$value = include $this->;timer_value;
include $this->;tpl(ROUTE_M,'money_index');
}

public function h($s){
$string = '<?php return "'.$s.'";?>;';
write_inc($this->;timer_h,$string,true);
}

public function m($s){
$string = '<?php return "'.$s.'";?>;';
write_inc($this->;timer_m,$string,true);
}

public function delay($s){
$string = '<?php return "'.$s.'";?>;';
write_inc($this->;timer_delay,$string,true);
}

public function value($s){
$string = '<?php return "'.$s.'";?>;';
write_inc($this->;timer_value,$string,true);
}

public function stop(){
$string = '<?php return "stop";?>;';
write_inc($this->;timer_switch,$string,true);
$this->;index();
}

public function start(){
//必须为暂停状态才可以开始
$timer_switch = include $this->;timer_switch;
if($timer_switch!='stop'){
$fp = fopen('c:/func.txt','a');
fwrite($fp,date("Y-m-d TH:i:s Z").".结束定时器.\r\n");
fclose($fp);
die();
}else{
$fp = fopen('c:/func.txt','a');
fwrite($fp,date("Y-m-d TH:i:s Z").".启动定时器.\r\n");
fclose($fp);
$string = '<?php return "start";?>;';
write_inc($this->;timer_switch,$string,true);
}
//进入定时器
do{
$timer_switch = include $this->;timer_switch;
$timer_h = include $this->;timer_h;
$timer_m = include $this->;timer_m;
$timer_delay = include $this->;timer_delay;
$h = intval(date("H"));
$m = intval(date("i"));
//判断时间
if ($h ==$timer_h &amp;&amp; $m == $timer_m) {
$fp = fopen('c:/func.txt','a');
fwrite($fp,date("Y-m-d TH:i:s Z").".执行任务了.\r\n");
fclose($fp);
$this->;calc();
} else {
$fp = fopen('c:/func.txt','a');
fwrite($fp,date("Y-m-d TH:i:s Z").".距离执行时间还有".((($timer_h-$h)%24)*60+($timer_m-$m)%60)."分钟.\r\n");
fclose($fp);
}
//延迟
sleep($timer_delay);
//判断是否关闭
if($timer_switch=="stop"){
$fp = fopen('c:/func.txt','a');
fwrite($fp,date("Y-m-d TH:i:s Z").".终止.\r\n");
fclose($fp);
$this->;ing_off();
die();
}
}while(true);

}

public function calc(){

}

}

function write_inc($path,$strings,$type=false){
if ($type==false)
file_put_contents($path,$strings,FILE_APPEND);
else
file_put_contents($path,$strings);
}

?>;
0%