PHP实现前后端分离的学生补考查询

前言


现在大部分高等院校所使用的教务系统均为方正软件开发的教务系统,在查询考试信息和补考时不方便。所以大部分院校都是直接导出补考信息,让各个学院老师自行通知或者建设一个简单的PHP MySQL站点,进行查询。这样有一些缺点:

  • 让老师通知通常只是把总表直接发到对应年级的年级群内,不会一对一通知,同学查询不便且公开了学生的成绩情况,有一定法律和舆论风险;
  • 大部分高等院校使用的PHP MySQL站点程序为示例程序,存在查询为空时的遍历,直接泄露所有补考名单,或者不检查查询语句,存在MySQL注入风险

于是,本文中,前后端分离的,基于csv文件的数据源查询PHP项目孕育而生。

项目地址


GitHub:https://github.com/little-gt/TOOLS-jwcstubukaosearch

技术实现


前后端分离

根据寻找的资料显示,现在大部分高校使用的PHP MySQL站点的源代码,其设计规范比较落后。体现在:

PHP后端代码不于HTML前端页面模版分离,采用混合式写法,这样虽然可以减少初期建设的工作量,但是会使得后期运维不方便。

解决的具体方法:

在我所创建的项目中,将PHP功能和HTML前端分开,PHP中不含有任何前端代码,所有前端模版都存放在/templates/文件夹中。日后如果需要修复后台逻辑等,只需要维护PHP文件;如果需要修改前端设计,也只需要维护HTML文件即可。

具体的,我们只需要在完成模版设计以后,使用下面的方法使得PHP读取我们的模版,然后输出即可:

// 读取模板文件
$templatePath = './templates/template1.html';

if (file_exists($templatePath)) {
    ob_start(); // 开始输出缓冲
    include $templatePath;
    $content = ob_get_clean(); // 获取缓冲区内容
    echo $content; // 输出内容
} else {
    echo "错误:无法加载模板文件";
}

不过很显然,在我们的设计中,需要PHP修改模版输出,这个时候就有两种不同的方案适用于不同的场景:

方法场景
占位符替换在HTML的特定位置嵌入占位符,比如{{html_placeholder}},让PHP在输出html模版时,替换出现占位符的地方,变成我们所需要的内容。
PHP嵌入在html内嵌入PHP输出代码,使得在读取模版文件时,将HTML中含有PHP逻辑的地方进行执行,动态根据传入内容进行输出和逻辑判断等复杂的工作。
占位符替换

显然占位符替换适合一些有限内容的展示,比如出现错误以后提醒用户错误原因,并且给出解决办法的情况,也就是报错。

示例
例如当学生输入不符合要求的内容以后,展示报错页面。这时只需要替换一小部分内容即可,符合占位符替换的使用场景。

那么我们只需要在展示信息的表格中,预留我们替换错误信息的占位符即可,为了方便后面的工程师维护,不妨将占位符取名为{{error_message}},那么就可以替换/templates/error.html的表单位置为下面的形式:

    <div class="error-box">
        <div class="logo">
            <img src="../logo.png" alt="西南大学教务处">
        </div>
        <div class="requirements">
            <h4>很抱歉,发生错误:</h4>
            <p>{{error_message}}</p>
        </div>
        <button class="return-home" onclick="location.href='../'">返回上一页</button>
    </div>

然后,在HTML后端中,将占位符{{error_message}}替换为我们所需要展示的错误信息,即:

// 读取模板文件
$templatePath = '../templates/error.html';

if (file_exists($templatePath)) {
    ob_start(); // 开始输出缓冲
    include $templatePath;
    $content = ob_get_clean(); // 获取缓冲区内容
    echo str_replace('{{error_message}}', $error, $content); // 替换模板中的占位符
} else {
    echo "错误:无法加载模板文件";
}

可以发现,我们只是简简单单的添加了一句代码,也就是替换占位符的代码,就实现了消息展示的目的,而不需要将HTML模版也写到PHP文件中,同时减少了PHP和HTML代码的阅读难度和维护难度。并且也符合了安全代码规范,避免因为HTML和PHP的相互影响,导致潜在的安全问题。

PHP代码嵌入

可是占位符替换虽然方便,但是面对输出学生详细补考情况,并且生成表格的时候就显得捉襟见肘了,我们不可能把以json格式的结果,在PHP转为HTML代码再替换。这样不就有点“画蛇添足”了吗?

这个时候,我们就想到,当PHP读入HTML模板文件以后,其实是可以在内存中执行读入的HTML中嵌入的PHP代码的。这个时候,虽然后台PHP和前端分离了,但是前端的逻辑部分还是会在后台PHP的读取下运行。

只需要保障PHP后端的变量使用和前端HTML嵌入的逻辑PHP代码变量使用一致即可。

我们不妨把查询的结果,以$results储存起来,这个时候,输出代码仍然不变,还是:

if (file_exists($templatePath)) {
    ob_start(); // 开始输出缓冲
    include $templatePath;
    $content = ob_get_clean(); // 获取缓冲区内容
    echo $content; // 输出内容
} else {
    echo "错误:无法加载模板文件";
}

但是,前端HTML代码中,相应的成绩展示部分就需要修改了,也就是在HTML表格中,插入下面的代码:

<?php 
      $totalSubjects = 0;
      $totalCredits = 0;
      foreach ($results as $row): 
          $totalSubjects += $row['计数']; // 计数每一科的值都是1
          $totalCredits += $row['学分']; // 用于判断是否显示学业警告
?>

$results中的json数据遍历储存到$row当中,方便我们后续直接输出。与此同时,我们还可以先预处理一下,该同学累计需要补考多少科目(也就是计数列的累加),以及累计需要补考的学分的多少。

执行完以后,立即在预处理之后,循环遍历输出查询结果,并且使用htmlspecialchars()方法,转换为html支持的编码即可。结束的时候,需要使用<?php endforeach; ?>告诉PHP,我们的表格已经结束啦,不然会死循环或者导致之后的html元素无法显示哦!

<?php 
    $totalSubjects = 0;
    $totalCredits = 0;
    foreach ($results as $row): 
        $totalSubjects += $row['计数'];
        $totalCredits += $row['学分'];
?>
    <tr>
        <td><?php echo htmlspecialchars($row['学号']); ?></td>
        <td><?php echo htmlspecialchars($row['姓名']); ?></td>
        <td><?php echo htmlspecialchars($row['行政班']); ?></td>
        <td><?php echo htmlspecialchars($row['课程代码']); ?></td>
        <td><?php echo htmlspecialchars($row['课程名称']); ?></td>
        <td><?php echo htmlspecialchars($row['学分']); ?></td>
        <td><?php echo htmlspecialchars($row['课程性质']); ?></td>
        <td><?php echo htmlspecialchars($row['总评成绩']); ?></td>
        <td><?php echo htmlspecialchars($row['任课教师']); ?></td>
        <td><?php echo htmlspecialchars($row['考试性质']); ?></td>
        <td><?php echo htmlspecialchars($row['考试具体时间']); ?></td>
        <td><?php echo htmlspecialchars($row['考试地点']); ?></td>
        <td><?php echo htmlspecialchars($row['计数']); ?></td>
    </tr>
<?php endforeach; ?>

搞定了表格,那怎么显示累计补考的学分和科目,并且进行判断呢?其实到这里,你也看出来了,无非就是把PHP代码写到HTML模版中,我们需要定制逻辑的地方而已。

显然,在我们需要显示这两个信息的地方插入PHP逻辑即可:

这时你应该也发现了,在上面循环遍历的时候,我们不需要让PHP嵌入HTML代码,只需要先使用HTML写好框架以后,在对应的需要PHP输出值的地方,写出PHP代码。并且在该结束的地方,告诉PHP结束即可。同理,if判断语句也不需要把HTML写到echo的内容中,只需要夹住对应的HTML代码即可。这与把HTML代码直接写到PHP里面效果是一样的!

<div class="summary">
    <p><strong>总计需补考科目数量:</strong> <?php echo $totalSubjects; ?></p>
    <p><strong>总计需补考学分数:</strong> <?php echo $totalCredits; ?></p>
    <?php if ($totalCredits >= 12): ?>
<p class="warning"><strong>警告:您需要补考的学分数已经达到或超过12分。</strong></p>
    <?php endif; ?>
</div>

示例
到这里我们就实现了补考页面的逻辑了!

使用csv查询代替MySQL

很显然,教务系统中导出的数据是以xlsx格式的Excel表格,转化为MySQL耗时而且对于教务处老师而言有技术门槛,不符合用户友好原则,那么有没有一种格式,既可以让PHP快速读取,又可以让教务处老师也可以轻松转换呢?

示例
可以看到,excel可以直接把xlsx另存为csv,不需要老师额外进行操作!

对啦,这不就是csv数据源格式吗!这个数据格式的存储是以文本string存储的,没有xml代码,形式如下:

学号,姓名,行政班,课程代码,课程名称,学分,课程性质,总评成绩,任课教师,考试性质,考试具体时间,考试地点,计数
123456789012345,张三,计算机科学与技术,CS101,计算机基础,6,必修,85,李老师,补考,2024-09-28 09:00,教学楼A201,1
123456789012345,张三,计算机科学与技术,CS102,数据结构,6,必修,90,王老师,补考,2024-09-28 10:00,教学楼A202,1
098765432109876,李四,软件工程,SW101,软件开发,3,选修,88,赵老师,补考,2024-09-28 11:00,教学楼A203,1

而且PHP中也有现成的方法,在不依赖外部库的情况下直接读取,即使用fgetcsv()方法:

// 打开CSV文件
if (($handle = fopen($filePath, "r")) !== FALSE) {
    // 读取标题行(如果有的话)
    $headers = fgetcsv($handle);

    // 逐行读取数据
    while (($data = fgetcsv($handle, 0, ",")) !== FALSE) {
        // 检查第一列(索引为0)是否为指定的学号
        if ($data[0] === $studentID) {
            // 将读取的数据转换为关联数组
            $rowData = array_combine($headers, $data);
            // 存储匹配的行数据
            $results[] = $rowData;
        }
    }

    fclose($handle); // 关闭文件句柄
}

就完成了从MySQL到csv直接查询的替换。

结语


综上就完成了主要的技术困难的攻关,之后的其实就只是运用上面的方法完成一些细节即可。

技术交流文档声明


本技术交流文档旨在促进参与者之间的信息共享和技术讨论,并仅用于非商业目的的技术研究与学习。本文档中的观点、结论及任何技术建议均不代表文中提及的任何单位、组织或个人的意见或立场。所有内容均基于撰写时可获得的信息,并可能随时更新而不另行通知。

请注意,本项目采用 MIT 许可协议发布,但并不保证:

  1. 代码或其他材料没有错误或者不会导致任何损害。
  2. 任何使用本项目代码或相关资源所产生的结果准确性或可靠性。
  3. 本项目能够满足特定用户的所有需求。

使用者应当自行承担使用本项目所带来的风险。对于因使用本项目所引起的任何形式的损失,作者及贡献者概不负责。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值