You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Moodle 3.10自定义测验提交事件插件触发失败修复请求

Moodle 3.10自定义测验提交JSON生成插件修复方案

问题概述

在Moodle 3.10开发本地自定义插件,目标是用户提交测验时生成包含用户、测验及成绩信息的JSON文件。已注册\mod_quiz\event\attempt_submitted事件观察者,事件可在管理员日志中看到,但插件的事件处理逻辑未触发,无法生成指定路径的JSON文件。

原代码问题分析

  1. 事件观察者缓存未更新:Moodle会缓存事件注册信息,新注册的观察者可能未生效
  2. Quiz实例获取错误:直接使用contextinstanceid作为Quiz ID不够严谨,需通过上下文对象验证后获取
  3. 文件路径与权限问题:Windows路径未转义,且未确保目标目录存在;Web服务器用户可能无读写权限
  4. 无错误捕获机制:处理过程中出现错误时无法排查,也无日志记录
  5. 文件覆盖风险:固定文件名会被后续提交覆盖

修复步骤与修改后代码

1. 清除Moodle缓存

登录站点管理员后台,进入站点管理 -> 开发 -> 清除缓存,确保事件观察者注册生效。

2. 修改事件处理类 (classes/event_handler.php)

添加错误捕获、日志记录,修正Quiz实例获取方式,优化文件路径处理:

<?php
namespace local_attempt_submission_plugin\classes;

defined('MOODLE_INTERNAL') || die();

class event_handler {
    public static function handle_attempt_submitted(\mod_quiz\event\attempt_submitted $event) {
        try {
            // 验证上下文并获取Quiz ID
            $context = $event->get_context();
            if ($context->contextlevel !== CONTEXT_MODULE) {
                debugging('事件上下文无效,非模块上下文', DEBUG_DEVELOPER);
                return;
            }
            $quizid = $context->instanceid;
            
            // 获取用户与Quiz快照记录
            $user = $event->get_record_snapshot('user', $event->userid);
            $quiz = $event->get_record_snapshot('quiz', $quizid);
            if (!$user || !$quiz) {
                debugging('无法获取用户或测验记录', DEBUG_DEVELOPER);
                return;
            }
            
            // 准备JSON数据
            $data = [
                'user_id' => $user->id,
                'username' => $user->username,
                'quiz_id' => $quiz->id,
                'quiz_name' => $quiz->name,
                'score' => $event->grade,
                'submitted_timestamp' => $event->timecreated,
                'submitted_at' => date('Y-m-d H:i:s', $event->timecreated)
            ];

            // JSON编码并检查错误
            $json_data = json_encode($data, JSON_PRETTY_PRINT);
            if ($json_data === false) {
                debugging('JSON编码失败: ' . json_last_error_msg(), DEBUG_DEVELOPER);
                return;
            }

            // 处理目标目录与文件路径
            $target_dir = 'C:\\sample\\';
            // 确保目录存在,不存在则创建
            if (!file_exists($target_dir)) {
                mkdir($target_dir, 0777, true);
            }
            // 使用测验尝试ID作为文件名后缀,避免覆盖
            $json_file_path = $target_dir . 'quiz_submission_' . $event->objectid . '.json';

            // 写入文件并检查结果
            $write_result = file_put_contents($json_file_path, $json_data);
            if ($write_result === false) {
                $error_msg = '无法写入JSON文件: ' . $json_file_path;
                debugging($error_msg, DEBUG_DEVELOPER);
                add_to_log(SITEID, 'local_attempt_submission_plugin', 'error', '', $error_msg);
            } else {
                add_to_log(SITEID, 'local_attempt_submission_plugin', 'success', '', 'JSON文件已生成: ' . $json_file_path);
            }
        } catch (\Exception $e) {
            $error_msg = '事件处理函数异常: ' . $e->getMessage();
            debugging($error_msg, DEBUG_DEVELOPER);
            add_to_log(SITEID, 'local_attempt_submission_plugin', 'exception', '', $error_msg);
        }
    }
}

3. 优化事件注册文件 (db/events.php)

显式设置internal参数,确保事件被正确捕获:

<?php
defined('MOODLE_INTERNAL') || die();

$observers = [
    [
        'eventname' => '\mod_quiz\event\attempt_submitted',
        'callback' => '\local_attempt_submission_plugin\classes\event_handler::handle_attempt_submitted',
        'internal' => false,
    ],
];

4. 其他必要设置

  • 权限检查:确保Moodle运行的Web服务器用户(如Windows下的IUSR、Linux下的www-data)对C:\sample\目录拥有读写权限
  • 启用调试:在config.php中添加$CFG->debug = DEBUG_DEVELOPER;,便于查看处理过程中的错误提示
  • 验证触发:可在事件处理函数开头添加add_to_log(SITEID, 'local_attempt_submission_plugin', 'trigger', '', '事件处理函数已触发');,确认函数是否被调用

内容的提问来源于stack exchange,提问作者Tamil Selvan s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 10:03:21