利用PHP实现简单的考勤打卡、人数统计功能。
这什么屑玩意啊,黑历史黑历史。
先讲个故事…
由于疫情原因,开学延迟,班主任为了监督我们学习,所以叫我们每天打卡。那么就要到群里点人,还要统计,谁打卡了谁没打卡谁迟到…我一想太麻烦了
于是我在群里水了一句,要不然开发个考勤系统吧
当然我当时的开发指的是“面向百度”编程(就是随便找个什么源码改一下title。
结果我发现行不通…没有符合我要求的源码,只好试试了。
我虽然接触了点编程,不过PHP还真没碰过,想想编程语言也都是26个字母只好硬着头皮干了。
要求
明确一下自己的期望吧:
- 能记录打卡人(开始就这一个想法)
好的没有了。
现在实现的功能(很多都是我晚上在被窝的新奇想法)
- 记录打卡人,打卡时间,自动标注准时或者迟到;
- 打卡成功后返回页面,提示成功与否并且提示信息(非常智障的实现,我跳转了一个html并且get传参信息,当时自己不知道php echo能输出html);(2021补:什么我为什么要用php echo来输出html???)
- 后台统计打卡人数、未打卡人数、迟到人数还有未打卡人名单;
准备
- 语言:思考来思考去,服务器只装着PHP,空间倒是有
.NET fw
,不过看看还是PHP的网站居多; - 实现:操作数据库一想就头大了,MySQL这玩意真玩不了,上次导入旧博客数据就差点没玩死我,想想还是直接磁盘上写文件吧;
- 服务器:本来想用我一个虚拟主机来着,不过那玩意权限有问题,写不了文件,无奈搬到网站服务器上面;
- IDE:没有专门去找PHP的IDE,直接用的vscode+网上随便找一个在线PHP作为调试;
开工
表单页面
表单创建
想来想去输入一个姓名就可以了,后来又想想需要一个时间,那么html如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>考勤打卡</title>
</head>
<body>
<form action="process.php" method="post">
姓名:<input type="text" name="name"><br>
时间:<input type="text" name="time"><br>
日期:<input type="text" name="filename"><br>
<input type="submit" value="打卡 ">
</form>
</body>
</html>
|
看起来是这样的:
(丑死了)
<!DOCTYPE html>
和 meta
是必须的,否则有可能乱码。
form
标签里面是表单,action
后面是提交到的地址,method
是方法(别问我为啥用 post
,因为它看起来好看)
input
中的 type
是输入的类型,text
自然就是文本啦,submit
是提交表单,name
是参数的名字(我日期参数是 filename
是因为我想把存储打卡信息的文件用日期命名),value
是默认的值。
时间获取
那么又一个问题来了,时间和日期怎么获取?这就要用的javascript
了,js
获取时间和日期后再去改动 html
,为了找到他们我把他们用 div
框起来然后给他们 id
为 0
和 1
(懒死了)
js
的时间获取百度一下就有,不过获取的都是浏览网页的人电脑上的时间,我怕别人通过修改本地时间来掩盖自己迟到的事实,所以我要去获取网络时间。
我的方法是 get
请求自己的服务器,在返回的头里面有时间信息(服务器的)。当然,你也可以百度一下时间 api
,调用起来也会很方便的。
js
代码如下:
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
| <script>
function getTime(){
ajax()
function ajax(option){
var xhr = null;
if(window.XMLHttpRequest) {
xhr = new window.XMLHttpRequest();
} else { // ie
xhr = new ActiveObject("Microsoft")
}
// 通过get的方式请求当前文件
xhr.open("get","/");
xhr.send(null);
// 监听请求状态变化
xhr.onreadystatechange = function(){
var time = null,
curDate = null;
if(xhr.readyState===2) {
// 获取响应头里的时间戳
time = xhr.getResponseHeader("Date");
curDate = new Date(time);
//下面修改HTML
document.getElementById("0").innerHTML = "时间:<input type='text' name='time' value='"+curDate.getHours()+":"+curDate.getMinutes()+"' readonly><br>";//拼接时间
document.getElementById("0").innerHTML = "日期:<input type='text' name='filename' value='"+curDate.getFullYear()+(curDate.getMonth()+1)+curDate.getDate()+"' readonly><br>";//通过readonly阻止修改时间
}
}
}
}
</script>
|
页面代码
因为HTML是顺序加载的,所以我希望 HTML
加载完全后再读取js
(否则 js
会找不到 id
为 0
的 div
),所以我们写个 onload
,为了刷新时间我在 getTime
函数里面利用 setTimeout
调用它自己实现定时(一分钟)刷新。HTML全文如下:
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
| <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>考勤打卡</title>
<script>
function getTime() {
ajax()
function ajax(option) {
var xhr = null;
if(window.XMLHttpRequest) {
xhr = new window.XMLHttpRequest();
} else { // ie
xhr = new ActiveObject("Microsoft")
}
// 通过get的方式请求当前文件
xhr.open("get","/");//可以把/改成https://www.baidu.com/
xhr.send(null);
// 监听请求状态变化
xhr.onreadystatechange = function() {
var time = null,
curDate = null;
if(xhr.readyState===2){
// 获取响应头里的时间戳
time = xhr.getResponseHeader("Date");
curDate = new Date(time);
//下面修改HTML
document.getElementById("0").innerHTML = "时间:<input type='text' name='time' value='"+curDate.getHours()+":"+cur.DateGetMinutes()+"' readonly><br>";//拼接时间
document.getElementById("1").innerHTML = "日期:<input type='text' name='filename' value='"+curDate.getFullYear()+(curDate.getMonth()+1)+curDate.getDate()+"' readonly><br>";//通过readonly阻止修改时间
}
}
}
setTimeout(getTime, 60000);
}
</script>
</head>
<body onload="getTime()">
<form action="process.php" method="post">
姓名:<input type="text" name="name"><br>
<div id="0"></div>
<div id="1"></div>
<input type="submit" value="打卡 ">
</form>
</body>
</html>
|
很可惜在自己家电脑上面是无法完成测试的,
把html上传到服务器之后效果是这样的:
虽然很丑,但是功能实现了,手动试一试确实无法修改时间、日期,而且时间也会每分钟刷新
PHP页面
由于PHP较为奇特的语法,和跟没有一样的报错,坑了我很长时间。PHP中字符串用 .
拼接、变量无需声明前面加上 $
即可…建议先过一遍菜鸟教程或者w3school
参数接收
PHP中接收到的POST的参数的值在
GET的在
参数处理
文件名
1
| $filename=$_POST["filename"]."txt";//拼接文件名
|
姓名
时间
1
2
3
4
5
6
7
8
9
| $time = str_replace(":","",$_POST["time"]);//把时间里的“:”去除掉
if ((int)$time>730)//7:30之后迟到
{
$name=$name."[迟到]";
}
else
{
$name=$name."[准时]";
}
|
写入文件
我使用的是函数
1
| file_put_contents(文件,内容,模式可选);
|
文件是文件的路径(字符串),比如/root/test.txt;(没有则创建一个文件)
注意:当无法创建且无法写入文件时,应该检查是否有权限。当能够创建但是无法写入文件时,应该检查首次写入的字符串是否为空,再检查后续代码是否有相关的操作覆盖了该文件,最后记得check一下你的磁盘空间(真的,我的硬盘满了,我检查了一天代码…)
内容是需要写入文件的内容;
模式是写入文件的模式,它包括:
- FILE_USE_INCLUDE_PATH //检查 filename 副本的内置路径?
- FILE_APPEND //添加模式更改文件,向文件的末尾加入字符串
- LOCK_EX //锁定文件
//如果模式为空则采用覆盖原内容的方式写入
它相对于 fopen
再 write
再 close
来说更简洁,功能上几乎是一样的。
我们写入的文件要求内容格式大致如下:
1
2
| 张三[准时] | 7:25
李四[迟到] | 7:33
|
这样后续我们可以通过计算“|”的数量来得出打卡人数,通过“[迟到]”的数量来得出迟到人数(当然我并不是这么办的,刚想起来这么机智的办法)
那么下面我们来写入文件:
1
2
3
| $str=$name." | ".$_POST["time"];
file_put_contents($filename,$str,FILE_APPEND);
echo "打卡成功";
|
那么PHP的全文是:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| <?php
$filename=$_POST["filename"]."txt";//拼接文件名
$name=$_POST["name"];
$time = str_replace(":","",$_POST["time"]);//把时间里的“:”去除掉
if ((int)$time>730)//7:30之后迟到
{
$name=$name."[迟到]";
}
else
{
$name=$name."[准时]";
}
$str=$name." | ".$_POST["time"]."\n";// \n的目的是在文件里面换行
file_put_contents($filename,$str,FILE_APPEND) or die("打卡失败");
echo "打卡成功";
?>
|
让我们把前面的HTML代码保存到 index.html
,上面的 php
保存到 process.php
,上传到服务器试试吧!
输入姓名提交表单:
POST到PHP,输出成功
如果PHP不输出任何内容,可以考虑在第一行加入一个 echo “test”; ,如果仍然不输出任何内容,那么可能是你的代码有问题
打卡前文件列表:
打卡后文件列表:
TXT内容:
(一)完结
实在是太累了,其他功能在后续的(二)中说
代码自己copy,成品会在(二)p.s.也没准是(三)中放出来
如果你觉得有用或者有需要补充之处不妨评论一下