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

Moodle课程模块增改时Observer未触发问题求助

Moodle课程模块事件观察者失效排查求助

在Moodle中尝试为course_module_updated和course_module_created事件添加Observer,但所有触发验证方式均未生效。已尝试清理全部缓存、写入文件日志、写入数据库日志、die()终止程序,均无效果。

疑问:是我的代码存在错误?还是事件已触发但日志代码未正常工作?

相关代码

db/events.php

defined('MOODLE_INTERNAL') || die();
use moodle_local_plugin\event\events_observer;

$observers = [
    [
        'eventname' => '\core\event\course_module_updated',
        'callback' => 'events_observer::course_module_updated',
        'includefile' => null,
        'internal' => true,
        'priority' => 9999
    ],
    [
        'eventname' => '\core\event\course_module_created',
        'callback' => 'events_observer::course_module_updated',
        'includefile' => null,
        'internal' => true,
        'priority' => 9999
    ],
];

classes/event/observer.php

namespace moodle_local_plugin\event;

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

class events_observer
{
    /**
     * Triggered when 'course_module_updated' event is triggered.
     *
     * @param \core\event\course_module_updated $event
     * @return bool
     */
    public static function course_module_updated(\core\event\course_module_updated $event)
    {
        global $DB, $CFG;
        // Log to DB
        $logdata = new \stdClass();
        $logdata->eventname = $event->eventname;
        $logdata->component = 'local_course_editor';
        $logdata->action = 'updated';
        $logdata->target = 'course_module';
        $logdata->objectid = $event->objectid;
        $logdata->timecreated = time();

        $DB->insert_record('log', $logdata);

        // Log the event data to a file
        $logfile = $CFG->dirroot . '/local/moodle_local_plugin/log.txt';
        $timestamp = date('Y-m-d H:i:s');
        $eventData = json_encode($event->get_data(), JSON_PRETTY_PRINT);
        $logMessage = "[{$timestamp}] Course module updated:
{$eventData}

";

        file_put_contents($logfile, $logMessage, FILE_APPEND);

        // end
        die(var_dump($event));
        //   return true;
    }
}

排查关键点

  • 命名空间与插件目录不匹配:
    观察者类命名空间为moodle_local_plugin\event,但日志中component写的是local_course_editor,如果插件实际目录是local/course_editor,则命名空间应改为local_course_editor\event,同时events.php中的use语句和回调路径也需同步修改,否则Moodle自动加载找不到类。
  • 事件回调参数类型不兼容:
    course_module_created事件的回调指定了course_module_updated方法,但该方法的参数类型是\core\event\course_module_updated,与实际触发的course_module_created事件类型不匹配,会触发PHP类型错误,导致观察者被静默跳过。
  • 数据库日志表字段缺失:
    直接往log表插入数据,但log表存在userid、contextid等必填字段,当前插入的$logdata缺少这些字段,会导致数据库插入失败,触发异常后后续代码(包括文件日志、die())都不会执行。
  • 文件日志路径错误:
    日志文件路径写的是/local/moodle_local_plugin/log.txt,如果插件目录不是moodle_local_plugin,则路径无效,且需确保该目录有写入权限,否则file_put_contents执行失败。
  • 调试模式未开启:
    未开启Moodle调试模式的话,PHP错误会被静默捕获,无法看到观察者执行过程中的报错信息。

修复建议

  1. 确认插件目录名,修正命名空间与events.php中的use语句,保证命名空间与文件路径严格对应(Moodle自动加载规则:classes/event/observer.php对应local_插件名\event\events_observer)。
  2. 为course_module_created事件单独编写回调方法,或修改现有方法参数为\core\event\base $event以兼容所有事件类型。
  3. 改用Moodle自带的add_to_log()函数记录日志,或补充log表所需的所有必填字段后再执行插入。
  4. 修正文件日志路径为插件实际目录,确保目录存在且服务器有写入权限。
  5. 在config.php中开启调试模式:
    $CFG->debug = E_ALL;
    $CFG->debugdisplay = true;
    
    开启后可直接看到执行过程中的错误信息。
  6. 清理缓存后,重新触发课程模块的创建/更新操作,验证观察者是否生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 07:03:21