ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

学生综合成绩管理系统实战:ThinkPHP+Laravel双框架整合与权重计算

学生综合成绩管理系统实战:ThinkPHP+Laravel双框架整合与权重计算 做学生成绩管理系统之前我也以为这事很简单无非是期末考试成绩录进系统按权重算个总分再排个名。真被教务处的老师拉去聊需求才发现他们要的“综合评价”跟我想的完全不是一回事——平时作业、课堂表现、项目答辩、竞赛加分、甚至一票否决项都要进总分而且不同课程权重还不一样以前这些全躺在老师的Excel表里各存一版期末汇总时错漏百出。我最后落地的方案是同时用了ThinkPHP和Laravel两套PHP框架一套管后台录入和权限一套管计算和API输出共享同一个MySQL库。这两个框架放在同一个项目里各干各的活听上去有点折腾但实际用下来边界特别清晰。这篇文章我就把这个方案的来龙去脉、数据模型、计算逻辑、以及部署时踩过的坑完整写出来给刚好要做类似成绩系统的人一个参考尤其是想整合多个PHP框架的同学应该能省不少弯路。1. 先想清楚“综合成绩”到底怎么算评价维度的拆解1.1 传统成绩方案的毛病如果只是“期末考试成绩×60% 平时成绩×40%”那确实不需要什么系统。但现实是老师手里的过程性数据特别多签到率、课堂提问、小组作业、实验报告、期中测试还有各类竞赛获奖加分。这些数据放Excel里第一个问题是版本管理混乱第二个问题是公式各有各的写法第三个问题是最后汇总时没人说得清某个分数是怎么来的。我这次的需求方明确提了一个指标每个学生的最终综合分必须能追溯到每个维度的原始得分和权重。也就是说系统里不存“综合分88.5”这种最终结果就完事而是要存“考试成绩90分、平时作业85分、课堂表现80分、竞赛加分5分按权重算出来88.5分”。这条要求直接决定了后面的表结构设计。1.2 综合评价维度的最终划分跟教务处反复讨论后我们把所有可量化的评价维度收敛成了四类学业成绩类期末考试、期中考试、平时测验、作业质量过程表现类出勤情况、课堂互动、实验实践、小组协作奖励加分项学科竞赛、论文发表、证书获取、志愿服务否决性指标考勤红线、学术诚信问题、考试违纪否决性指标比较特殊它不参与“加权重”算法而是直接判定等级上限。比如学生一旦有学术不端记录无论总分多高综合等级最高只能到C。这块逻辑一开始没设计进去后来补上时改了不少代码所以我建议从一开始就在需求里把这类规则点出来。1.3 不同课程类型权重配置权重不能写死在代码里这是我做这类系统最深的体会。不同院系、不同课程评价侧重完全不同思政课重平时表现实操课重项目和实验理论课重期末考试。我最终用的是数据库配置权重组的方式大致这样课程类型考试成绩平时作业课堂表现实践环节竞赛加分理论必修课50%20%15%10%5%实验实践课30%15%10%40%5%体育艺术课20%30%40%10%0%选修通识课40%25%20%15%0%每组权重存成一条配置记录对应到课程分组。权重总和也不是强制100%引擎那里会做归一化处理这个后面讲到具体计算时细说。1.4 百分制到等级制的换算综合分是百分制但学院最终公示时用的是五级制优秀、良好、中等、及格、不及格成绩单上还要带学分绩点。换算规则也要可配置我用的标准是90-100分优秀绩点4.080-89分良好绩点3.070-79分中等绩点2.060-69分及格绩点1.00-59分不及格绩点0这条规则放在了数据库参数表里而不是写死在代码中。后来有学院要求优秀率控制在20%以内他们只要调参数就行不用动代码。2. 为什么一个项目里同时用ThinkPHP和Laravel2.1 项目背景既有遗留系统需求方已有的教务管理后台是用ThinkPHP 5.1写的跑了好几年稳定。但这次的综合评价模块计算逻辑复杂还要对接学生端的查询API直接在老代码上堆功能也可以但想想以后要加队列、加缓存、加单元测试Laravel的生态明显更合适。所以我的方案不是“抛弃ThinkPHP重写”也不是“只用Laravel替换”而是让两个框架在同一套系统里共存ThinkPHP保留已有的管理后台能力Laravel承载新模块的计算和API。2.2 框架分工模块使用框架具体职责教师成绩录入ThinkPHP表单、批量导入、草稿保存、数据校验教务审核发布ThinkPHP审核工作流、成绩锁定、发布管理学生信息管理ThinkPHP班级、学籍、课程分组维护综合评价计算Laravel权重归一化、聚合计算、排名学生查询APILaravel成绩查询、明细追溯、报表导出消息通知Laravel队列发送成绩发布通知、生成PDF两个框架部署在同一台服务器、同一个域名下的两个子目录共享同一个MySQL数据库。因为各自入口不同路由不会冲突。2.3 为什么这样分三个实际理由第一团队上手成本低。老团队闭着眼睛能写ThinkPHP让他们学新框架还要时间。ThinkPHP这边照常维护老功能新模块的复杂逻辑交给Laravel两边没有互相绑架的感觉。第二计算和API放Laravel侧更顺手。综合评价计算要写服务类、要做单元测试、要有队列异步处理Laravel的Artisan命令行、Eloquent模型、Queue系统都是现成的。计算引擎跑在CLI环境里比Web环境更稳定。第三边界清晰以后好逐步演进。如果哪天老后台某个模块也该升级了可以一层层往Laravel迁移而不是推倒重来。这套结构跑了大半年我自己最直观的感受是改ThinkPHP代码时不用担心碰坏计算逻辑改Laravel代码时不用担心把后台界面搞崩。2.4 两个框架之间的接口约定两个框架不能用同一个session所以它们之间完全不共享Web会话而是通过一个简单的内部API交换数据Laravel侧提供/internal/api/score/aggregate接口接收student_ids、course_id、term参数ThinkPHP侧在审核发布时调用这个接口触发某个班级某门课的综合分计算请求头带上内部token双方约定统一返回结构code、message、data这个接口不对外网暴露只监听内网地址。如果两个框架不在同一台机器上就用内网IP加token调用。2.5 为什么不直接上微服务有人可能会问两个框架都放一起了为什么不直接搞微服务说实话这个体量完全够不到微服务的层次一共就一个学校几千名学生。微服务带来的服务发现、链路追踪、分布式事务对这个项目是纯粹的负担。两个框架共享一个MySQL计算结果统一写库事务边界简单出了问题也好排查。3. 数据模型可配置规则的表结构3.1 明细行优先拒绝宽表一开始我也想过用宽表“一个学生一行二十个字段分别是各种成绩”但很快放弃了。因为评价维度会调整宽表加一个字段就是一次表结构变更。改成明细行之后加维度不需要改表结构只是多插几行数据灵活得多。核心表设计成四张成绩明细表保存每个学生每个课程每个维度的原始得分维度参数表定义有哪些维度、默认权重、分值范围权重分组表不同课程类型对应的权重配置综合结果表保存计算后的总分、等级、排名3.2 成绩明细表结构CREATE TABLE score_detail ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, student_id INT UNSIGNED NOT NULL COMMENT 学生ID, course_id INT UNSIGNED NOT NULL COMMENT 课程ID, academic_year VARCHAR(20) NOT NULL COMMENT 学年如2024-2025, term TINYINT NOT NULL COMMENT 学期1或2, dimension_code VARCHAR(30) NOT NULL COMMENT 维度代码如exam_score, raw_score DECIMAL(5,2) NOT NULL COMMENT 原始得分, weight DECIMAL(5,2) NULL COMMENT 本记录权重可覆盖默认权重, score_source TINYINT NOT NULL DEFAULT 1 COMMENT 来源1手动录入 2Excel导入 3系统计算, operator_id INT UNSIGNED NOT NULL COMMENT 操作人ID, remark VARCHAR(255) DEFAULT NULL COMMENT 备注如补考/缓考/竞赛加分, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY idx_student_course (student_id, course_id), KEY idx_course_term (course_id, term) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生成绩明细表;这里有一个容易被忽略的点weight字段允许为空为空时走权重分组表里配置的默认权重。这样好处是支持“某次考试成绩权重调整”的特殊情况不用新增一张覆盖表。但坏处是业务逻辑里要多判断一次后面计算引擎会做统一处理。3.3 维度参数表和权重分组表CREATE TABLE score_dimension ( dimension_code VARCHAR(30) PRIMARY KEY, dimension_name VARCHAR(50) NOT NULL, default_weight DECIMAL(5,2) NOT NULL DEFAULT 0, min_score DECIMAL(5,2) NOT NULL DEFAULT 0, max_score DECIMAL(5,2) NOT NULL DEFAULT 100, is_deductible TINYINT NOT NULL DEFAULT 1 COMMENT 是否为扣分项, sort_order INT NOT NULL DEFAULT 0 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT评价维度参数表; CREATE TABLE score_weight_group ( id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, group_name VARCHAR(50) NOT NULL COMMENT 权重组名, course_type VARCHAR(30) NOT NULL COMMENT 课程类型编码, dimension_code VARCHAR(30) NOT NULL, weight DECIMAL(5,2) NOT NULL, valid_from DATE NOT NULL COMMENT 生效日期, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_type_dim (course_type, dimension_code, valid_from) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT权重分组配置表;权重配置加上valid_from日期以后权重调整就是插入一条新配置历史成绩依然按旧权重计算和回溯不会因为参数改了导致往期成绩全部变化。这一点在我们上线后第二次调整权重时发挥了很大作用——有几个学院一直用历史数据核对排名如果没有这个字段根本说不清楚某学期为什么总分变了。3.4 综合结果表为什么存结果而不是实时算有的同学觉得综合分实时算不就行了省一张表。我解释一下为什么最终要落一张结果表成绩发布后学生端、教师端、打印成绩单、导出报表都在高频读取综合分。如果每查询一次就聚合一次轻则SQL慢重则计算逻辑在不同页面出现微妙不一致。CREATE TABLE score_result ( id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, student_id INT UNSIGNED NOT NULL, course_id INT UNSIGNED NOT NULL, academic_year VARCHAR(20) NOT NULL, term TINYINT NOT NULL, total_score DECIMAL(5,2) NOT NULL COMMENT 综合分, grade_level VARCHAR(10) NOT NULL COMMENT 等级优秀/良好/中等/及格/不及格, credit_point DECIMAL(3,1) NOT NULL COMMENT 绩点, class_rank INT DEFAULT NULL COMMENT 班级排名, score_json JSON NOT NULL COMMENT 各维度得分存档用于追溯, version INT NOT NULL DEFAULT 1 COMMENT 版本号每次重算1, status TINYINT NOT NULL DEFAULT 1 COMMENT 1草稿 2已发布, published_at DATETIME NULL, created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, UNIQUE KEY uk_stu_course_term (student_id, course_id, academic_year, term) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT综合成绩结果表;score_json字段很关键。它把计算时使用的各个维度得分、权重一并存下来不管以后权重参数怎么改这条结果都能完整追溯当时的依据就是前面说的“每个分数都有来处”。4. 计算引擎实现权重归一化和状态流转4.1 引擎为什么要放在Laravel侧计算引擎我放在了Laravel侧用Command注册支持手动触发和定时任务触发。原因就一条Laravel的Eloquent配合模型事件做数据聚合时写起来比ThinkPHP模型更顺手而且更容易单测。计算引擎不依赖UI它只做一件事读取明细表数据按维度加权聚合写入结果表。4.2 核心计算公式综合分的计算公式看着简单但有几个细节必须处理权重归一化如果配置的权重总和不是100%不直接报错而是按比例缩放。比如某门课只配了考试60%和作业30%总和90%实际计算时考试、作业分别按66.67%和33.33%参与。加分项替换竞赛加分这类奖励加分在100分制里会导致总分超过100需要设定加分上限默认单科总分封顶100。否决项判定存在一票否决记录时总分不做特殊处理但等级直接降级。公式可以写成normalized_weight_i config_weight_i / sum(config_weight_i) dimension_score_i raw_score_i * normalized_weight_i total_score min(100, sum(dimension_score_i) bonus_score)4.3 Laravel核心服务类计算聚合我写成一个独立的ScoreCalculator服务类?php namespace App\Services; use App\Models\ScoreDetail; use App\Models\ScoreResult; use App\Models\ScoreWeightGroup; use Illuminate\Support\Facades\DB; class ScoreCalculator { public function calculate(int $courseId, string $academicYear, int $term): void { $studentIds ScoreDetail::where(course_id, $courseId) -where(academic_year, $academicYear) -where(term, $term) -distinct() -pluck(student_id); foreach ($studentIds as $studentId) { $this-calculateForStudent($studentId, $courseId, $academicYear, $term); } } public function calculateForStudent(int $studentId, int $courseId, string $academicYear, int $term): array { $details ScoreDetail::where(student_id, $studentId) -where(course_id, $courseId) -where(academic_year, $academicYear) -where(term, $term) -get(); // 取权重配置优先明细表上的覆盖权重否则取权重组配置 $weights []; foreach ($details as $detail) { $weights[$detail-dimension_code] $detail-weight ?? $this-getDefaultWeight($detail-dimension_code); } $weightSum array_sum($weights); if ($weightSum 0) { throw new \RuntimeException(权重总和必须大于0); } $totalScore 0.0; $scoreJson []; foreach ($details as $detail) { $normalizedWeight $weights[$detail-dimension_code] / $weightSum; $itemScore $detail-raw_score * $normalizedWeight; $totalScore $itemScore; $scoreJson[$detail-dimension_code] [ raw_score (float) $detail-raw_score, weight (float) $weights[$detail-dimension_code], normalized_weight round($normalizedWeight, 4), item_score round($itemScore, 2), ]; } // 加分项上限处理 $bonusScore $this-calculateBonus($details); $totalScore min(100, $totalScore $bonusScore); // 一票否决判定 $hasVeto $this-hasVetoRecord($studentId, $courseId, $academicYear, $term); $grade $this-convertToGrade($totalScore, $hasVeto); $creditPoint $this-gradeToCreditPoint($grade); // 写入结果表 ScoreResult::updateOrCreate( [ student_id $studentId, course_id $courseId, academic_year $academicYear, term $term, ], [ total_score round($totalScore, 2), grade_level $grade, credit_point $creditPoint, score_json $scoreJson, version DB::raw(version 1), ] ); return $scoreJson; } }这段逻辑看着不长但有两个地方我建议你特别注意。第一是DB::raw(version 1)每次重算都会递增版本方便查问题。第二是把score_json完整存下来就算有人事后修改了原始成绩结果表里依然保留了计算当时的全部数据。4.4 状态机草稿、审核、锁定、发布综合成绩不能教师录完就直接生效那是给自己挖坑。我设计了一个状态流转流程草稿态教师录入或导入成绩存score_detail表结果表没有记录审核态教务审核成绩明细此时可以退回给教师修改锁定态审核通过后先锁定明细禁止修改发布态触发计算引擎写入结果表学生端可见这个状态不是只放在某个字段里而是拆成了两个维度score_detail表有audit_status字段score_result表有status字段。发布以后发现某个分数确实录错了不能直接在表里改要走“重新开放→修改→重新审核→重算发布”的流程。这个机制让管理员权限边界非常清晰。4.5 缺考、缓考、重修这些边界情况真实业务里最考验系统的其实不是正常成绩而是各种边界情况缺考/缓考考试成绩维度存NULL。计算引擎遇到NULL时该维度按0参与权重但结果表里备注为“缺考”等级上限设为及格。重修覆盖同一门课学生重修后取最高一次成绩作为有效成绩但要在结果表保留两次计算记录方便审计。权重总和不是100%前面代码已经处理按比例归一化。这是我调试时踩过的坑有门课的权重表漏配了一项算出来全班成绩低了一截加了归一化处理以后配置的问题至少不会导致结果彻底失真。4.6 缓存与异步发布成绩发布那个瞬间整个年级几千学生几百门课一起触发计算Web请求明显变慢。我的做法是发布操作只往队列里推一个任务Laravel队列处理聚合计算完成后用事件通知教务老师。学生端查询走Redis缓存发布后第一次查询回源数据库之后直接读缓存。这块如果你只是小范围用几十个学生几百条记录确实不需要队列。但我这个场景是全校性的队列方案让发布操作从几十秒降到了几百毫秒响应体验差别很大。5. 教师录入和Excel批量导入的实现细节5.1 ThinkPHP端的录入表单与事务ThinkPHP这边主要做的是“把数据好看地收进来”。单个成绩录入页面我用了常规的POST表单控制器里做了三件事public function store() { $data $this-request-post(); // 1. 验证 $validate new ScoreValidate(); if (!$validate-check($data)) { return json([code 1, msg $validate-getError()]); } // 2. 事务写入明细 Db::startTrans(); try { $scoreDetail ScoreDetailModel::create([ student_id $data[student_id], course_id $data[course_id], academic_year $data[academic_year], term $data[term], dimension_code $data[dimension_code], raw_score $data[raw_score], score_source 1, operator_id session(admin_id), ]); Db::commit(); return json([code 0, msg 保存成功]); } catch (\Exception $e) { Db::rollback(); return json([code 1, msg 保存失败 . $e-getMessage()]); } }为什么这里加事务因为同一门课程多个维度的成绩可能一次性提交如果一个维度写成功、另一个维度写失败成绩明细就少了数据计算综合分时权重会对不上。加上事务要么全成功要么全回滚。5.2 Excel模板设计单条录入只适合补充个别数据期中期末大规模录成绩还是得靠Excel。我设计了一个固定模板第一列学号第二列课程编号后面的列是各个维度代码比如exam_score、homework_score、class_performance。模板第一行是维度名第二行是维度代码第三行起是数据。模板这么设计是有原因的老师的原始Excel五花八门有的列叫“考试成绩”有的叫“期末成绩”还有直接写“总评”。系统无法猜测列名所以我的方案是让教务先把自己的数据结构整理成标准模板然后我在导入逻辑里做严格校验不靠猜。5.3 批量导入的校验链批量导入我用的是phpoffice/phpspreadsheet库ThinkPHP里直接Composer引入就行。导入逻辑分三段读文件校验后缀必须是模板允许的xlsx或xls超过2MB直接拒绝逐行校验学号在student表里是否存在、课程号是否存在、分数是否在维度允许范围内、维度代码是否在配置表里落库校验同一学生同一课程同一维度不能有重复记录有则更新无则插入逐行校验错误信息要具体到行号和列名不能只给“数据有误”四个字。比如Excel行号错误原因5学号2024010103不存在12维度代码project_score未配置18课堂表现分130超出0-100范围27该学生此维度已有成绩系统已更新这个错误报告生成后教师可以当场在Excel里改再重新上传不用一行行去后台改。5.4 权限控制与操作留痕权限分四层教务处能配置权重、审核、重算成绩学院管理员能管理本学院课程和教师任课教师只能录自己教的课且只能改草稿态数据学生只有只读查询权限。每次录入、修改、导入、重算、发布都要写操作日志。我用了最简单的方案建一张score_operation_log表记录操作人、操作类型、目标记录ID、操作前后快照。这里没有用什么很高级的审计中间件但已经能回答“这分数谁改的、什么时候改的、改了什么都、为什么改”这四个问题。5.5 成绩审核发布的人性化细节审核界面要能让教务直观看到差异。我做了对比视图左边是教师提交的原始分右边是当前结果表的成绩中间列出修改痕迹。审核人不需要来回切换页面就能判断是否退回。退回到教师端时系统自动生成一条待办提醒教师登录后台就能看到哪些班级的成绩被打回了原因是什么。这个小功能在沟通成本上省了非常多原来教务跟老师之间靠微信群来回传话现在全在系统里闭环。6. 部署上线与安全加固两个框架同存的那些坑6.1 运行环境清单这套系统的运行环境我用的是LNMPPHP版本定在8.1。两个框架对PHP版本要求不一样ThinkPHP 5.1本来PHP 7.x也没问题但我统一升到8.1后基本能跑唯一要注意的是得把框架版本升级到最新小版本老版本在PHP 8下会有兼容问题。组件版本说明CentOS7.9服务器操作系统Nginx1.24Web服务器PHP8.1CLI和FPM都配置MySQL8.0数据库Redis7.0缓存和sessionComposer2.7依赖管理6.2 目录规划与Nginx配置我把两个框架放在两个子目录/var/www/html/ ├── tphp/ # ThinkPHP入口访问地址 /admin └── laravel/ # Laravel入口访问地址 /apiNginx配置里/admin走ThinkPHP的public目录/api走Laravel的public目录server { listen 80; server_name score.example.com; # ThinkPHP后台 location /admin { alias /var/www/html/tphp/public; try_files $uri $uri/ /admin/index.php?s$uri$args; index index.php; } # Laravel API location /api { alias /var/www/html/laravel/public; try_files $uri $uri/ /api/index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $request_filename; include fastcgi_params; } }Nginx配置有个坑要提醒两个框架的location块如果都配置了try_filesNginx解析$uri时如果不能正确取到文件路径会让PHP直接跑在错误的SCRIPT_FILENAME上。我调了半天最后确认是alias加try_files的配合问题改成了上面的写法才稳定。6.3 Session统一到Redis两个框架最开始各自用各自的session驱动然后问题就来了用户在ThinkPHP后台登录跳转到Laravel的查询页面又要求重新登录。由于Laravel侧只提供API其实不需要同一套session但浏览器端管理界面和API有交叉调用统一最省事。最终方案是两个框架的session驱动都配置为Rediskey前缀不同但共享同一个Redis实例。这样至少不会出现“ThinkPHP写入的session Laravel读不到”的诡异现象。如果你也同时跑两套框架这一步建议提前做别等用户反馈才处理。6.4 安全加固清单这类系统涉及学生成绩数据敏感安全上不能只靠框架默认配置。我最后落实的清单如下参数过滤所有输入框做白名单验证学号必须是数字分数必须匹配/^\d{1,3}(\.\d{1,2})?$/CSRF保护ThinkPHP的表单开启token验证Laravel API用middleware处理跨域预检SQL注入两个框架都强制走模型和查询构造器不拼原生SQL查询构造器解决不了的地方用预处理依赖安全Composer定期跑composer audit发现第三方包漏洞及时升级。框架版本要保持在官方支持的版本线老版本暴露安全问题的风险会越来越高敏感数据脱敏列表页默认隐藏完整学号只显示后四位导出Excel要设置权限校验下载链接带时效性token操作日志所有变更都记录日志日志文件禁止写入Web根目录6.5 我踩过的三个典型问题第一个是CLI和FPM的环境差异。Laravel队列在CLI下跑读取的.env和配置跟FPM不一样。我一开始没注意队列任务里用了相对路径结果发布通知里的PDF生成路径在命令行下全错了。解决方法是所有路径一律用绝对路径或者用base_path()这类框架封装的函数。第二个是时区问题。PHP默认时区是UTC中国用户看到的时间差了8小时。我统一在php.ini里设置了date.timezone Asia/Shanghai同时Laravel的config/app.php里的timezone也要改成Asia/Shanghai两边对不上就会出现成绩发布时间错乱。第三个是上传限制。Excel文件稍微大一点就上传失败排查下来是Nginx的client_max_body_size默认只有1M。我把这个值调整到了20M同时在ThinkPHP的upload配置里同步改了限制两个地方都改了才生效。最后再说两句经验这套系统从需求调研到上线前后大概花了两个月。如果让我重新做一次最大的调整是不要一上来就建那么多表、做那么复杂的审核流。先跑通最小闭环——教师录成绩、引擎算总分、学生查结果这个链条通了之后再一步步加权重配置、加审批、加导入导出每加一个功能都验证一下不影响已有数据。我前期在宽表设计上犹豫了一周最后推翻重来这个教训挺深刻。还有一个很实际的经验成绩系统最重要的不是技术炫不炫而是数据能不能追溯。任何一条综合分你都要能点开看到它是怎么算出来的、每个维度原始分是多少、权重是谁配的、什么时候生效的。有了这个底子后续不管领导要什么报表、什么排名分析都不用慌。如果你也要做类似的学生综合评价系统或者正纠结ThinkPHP和Laravel该选哪个我的看法是不必选。老系统是ThinkPHP就继续用它处理熟练的增删改查新模块需要复杂计算和API就用Laravel中间用一张共享数据库和简单的内部接口对接完全可行。关键是边界划清楚别让两个框架互相渗透维护起来就没那么可怕。
返回列表