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

Moodle本地插件订阅Quiz模块「全部提交并完成」事件求助

问题描述

在Windows平台上为Moodle 2023042400(4.2.2+)开发本地插件local/adaptive_quiz/,需要订阅Quiz模块「全部提交并完成」事件,获取测试完成后的错误答案,仅需实现事件订阅与数据获取,使用PHP开发。插件已通过before_footer回调验证可正常运行,但此前的事件订阅方案均无效。

已尝试的无效方案

  • 研究Moodle源码了解到single_button类创建按钮,但未掌握事件订阅与数据获取方法
  • 通过方法名订阅预设事件,无效果
  • 通过$handlers变量订阅事件,指定处理方法未被调用

正确的事件订阅与数据获取实现步骤

1. 确认目标事件的正确名称

Moodle 4.x中,「全部提交并完成」对应的标准事件是\mod_quiz\event\attempt_submitted,而非旧版格式的quiz_attempt_submitted,这是之前订阅失败的核心原因之一。

2. 采用事件观察者模式实现订阅

Moodle 4.x推荐使用**事件观察者(Event Observer)**机制处理事件订阅,替代旧的$handlers数组方式,以下是具体实现:

步骤2.1 创建观察者类文件

在插件目录下新建classes/observer.php,写入以下代码:

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

class local_adaptive_quiz_observer {

    /**
     * 处理测验提交完成事件
     * @param \mod_quiz\event\attempt_submitted $event
     */
    public static function handle_quiz_submitted(\mod_quiz\event\attempt_submitted $event) {
        // 日志验证事件触发
        error_log('local_adaptive_quiz: 测验提交事件已触发');

        // 获取当前测验尝试ID
        $attemptid = $event->objectid;

        // 获取用户错误答案
        $wrongAnswers = self::getUserWrongAnswers($attemptid);

        // 输出错误答案到日志(后续可替换为界面展示逻辑)
        error_log('local_adaptive_quiz: 用户错误详情:' . print_r($wrongAnswers, true));
    }

    /**
     * 提取用户测验尝试中的错误答案
     * @param int $attemptid 测验尝试ID
     * @return array 错误答案数组
     */
    private static function getUserWrongAnswers($attemptid) {
        global $DB;
        $wrongAnswers = [];

        // 获取当前测验尝试的基础信息
        $attempt = $DB->get_record('quiz_attempts', ['id' => $attemptid], '*', MUST_EXIST);
        // 获取测验下的所有题目槽位
        $slots = $DB->get_records('quiz_slots', ['quizid' => $attempt->quiz]);

        foreach ($slots as $slot) {
            // 获取用户该题的答题记录
            $response = $DB->get_record('quiz_responses', [
                'attemptid' => $attemptid,
                'slot' => $slot->slot
            ]);
            if (!$response) continue;

            // 加载题目实例,用于验证答案正确性
            $question = question_load_questions([$slot->questionid])[$slot->questionid];
            $questionEngine = question_engine::load_question($question);

            // 转换用户答案格式并验证是否错误
            $userResponse = $questionEngine->get_response_summary($response->answer);
            if (!$questionEngine->is_correct_response($userResponse)) {
                $wrongAnswers[] = [
                    'question_id' => $slot->questionid,
                    'question_name' => $question->name,
                    'user_answer' => $response->answer,
                    'correct_answer' => $questionEngine->get_correct_response()
                ];
            }
        }

        return $wrongAnswers;
    }
}

步骤2.2 注册事件观察者

在插件目录下新建db/events.php,注册观察者与事件的关联:

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

$observers = [
    [
        'eventname' => '\mod_quiz\event\attempt_submitted',
        'callback' => 'local_adaptive_quiz_observer::handle_quiz_submitted',
        'priority' => 10,
        'internal' => false,
    ],
];

3. 更新插件并清除缓存

  1. 修改version.php中的版本号(递增即可,触发Moodle插件更新机制):
<?php
defined('MOODLE_INTERNAL') || die();

$plugin->version  = 2023090901; // 版本号从原2023090900递增
$plugin->requires = 2023042400;
$plugin->pluginname = 'Adaptive Quiz';
$plugin->component = 'local_adaptive_quiz';
?>
  1. 登录Moodle后台,进入「站点管理」→「插件」→「插件检查」,执行插件更新。
  2. 清除Moodle缓存:「站点管理」→「开发」→「清除缓存」。

4. 验证事件触发

提交任意测验并点击「全部提交并完成」,查看Moodle错误日志(Windows下通常位于moodledata/logs/目录或PHP错误日志),若看到local_adaptive_quiz: 测验提交事件已触发及错误答案详情日志,说明事件订阅成功。

关键注意事项

  • 事件名称必须准确:Moodle 4.x强制使用命名空间格式的事件名,旧格式quiz_attempt_submitted已不再生效。
  • 缓存必须清除:修改事件注册或观察者类后,必须清除Moodle缓存,否则新代码不会被加载。
  • 题型兼容:示例仅适配选择题的错误答案判断,填空题、简答题等其他题型需根据题型调整答案验证逻辑。

内容的提问来源于stack exchange,提问作者Betrayal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:44:51