如何通过Local插件重写Moodle核心分类表单以添加更多字段?
解决方案:用Local插件扩展Moodle分类表单
完全可以通过Local插件实现分类表单的字段扩展,你之前的问题在于直接沿用核心表单的文件结构——Moodle会优先加载核心文件,因此需要通过表单继承+钩子拦截的方式替换系统默认表单。
具体操作步骤
1. 创建自定义表单类,继承核心表单
在Local插件目录下新建classes/form/editcategory_form.php,编写自定义表单类,继承核心的editcategory_form并添加字段:
defined('MOODLE_INTERNAL') || die(); // 加载核心分类表单文件 require_once($CFG->dirroot . '/course/editcategory_form.php'); class local_yourplugin_editcategory_form extends editcategory_form { protected function definition() { // 先加载核心表单的原有字段 parent::definition(); $mform = $this->_form; // 添加自定义字段(示例为文本框,可按需修改为下拉框、编辑器等) $mform->addElement('text', 'custom_category_field', '自定义分类字段'); $mform->setType('custom_category_field', PARAM_TEXT); // 可选:添加帮助按钮,需在插件语言包中配置对应帮助文本 $mform->addHelpButton('custom_category_field', 'custom_category_field', 'local_yourplugin'); } protected function definition_after_data() { parent::definition_after_data(); $mform = $this->_form; // 从自定义表中读取已有值,填充到表单 $categoryid = $this->_customdata['category']->id ?? 0; if ($categoryid) { global $DB; $fielddata = $DB->get_record('local_yourplugin_category_fields', ['categoryid' => $categoryid]); if ($fielddata) { $mform->setDefault('custom_category_field', $fielddata->custom_field); } } } }
2. 拦截核心表单加载,替换为自定义类
在插件的lib.php中通过before_http_headers钩子,在核心表单加载前替换类指向:
defined('MOODLE_INTERNAL') || die(); function local_yourplugin_before_http_headers() { global $PAGE; // 仅在分类编辑页面生效 if ($PAGE->pagetype === 'course-editcategory') { // 加载自定义表单类 require_once($CFG->dirroot . '/local/yourplugin/classes/form/editcategory_form.php'); // 将核心表单类别名为自定义类,让系统实例化时调用我们的表单 class_alias('local_yourplugin_editcategory_form', 'editcategory_form'); } }
3. 存储自定义字段数据
3.1 创建数据库表
在插件的db/install.xml中定义存储自定义字段的表:
<?xml version="1.0" encoding="UTF-8"?> <XMLDB PATH="local/yourplugin/db" VERSION="2024010100" COMMENT="Custom category fields storage"> <TABLE NAME="local_yourplugin_category_fields" COMMENT="Stores custom fields for course categories"> <FIELDS> <FIELD NAME="categoryid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Linked course category ID"/> <FIELD NAME="custom_field" TYPE="text" NOTNULL="false" COMMENT="Value of the custom field"/> </FIELDS> <KEYS> <KEY NAME="primary" TYPE="primary" FIELDS="categoryid"/> <KEY NAME="categoryid" TYPE="foreign" FIELDS="categoryid" REFTABLE="course_categories" REFFIELDS="id"/> </KEYS> </TABLE> </XMLDB>
3.2 监听分类保存事件,存储字段值
在插件的db/events.php中注册事件监听:
<?xml version="1.0" encoding="UTF-8"?> <EVENTS> <EVENT NAME="core_course_category_created"> <HANDLER FUNCTION="local_yourplugin_save_custom_field" METHOD="standard"/> </EVENT> <EVENT NAME="core_course_category_updated"> <HANDLER FUNCTION="local_yourplugin_save_custom_field" METHOD="standard"/> </EVENT> </EVENTS>
然后在lib.php中实现保存逻辑:
function local_yourplugin_save_custom_field($event) { global $DB; $categoryid = $event->objectid; $customvalue = optional_param('custom_category_field', '', PARAM_TEXT); // 更新或插入记录 $record = $DB->get_record('local_yourplugin_category_fields', ['categoryid' => $categoryid]); if ($record) { $record->custom_field = $customvalue; $DB->update_record('local_yourplugin_category_fields', $record); } else { $newrecord = new stdClass(); $newrecord->categoryid = $categoryid; $newrecord->custom_field = $customvalue; $DB->insert_record('local_yourplugin_category_fields', $newrecord); } }
4. 升级插件并测试
- 进入Moodle站点管理的「插件升级」页面,完成插件升级
- 打开分类编辑页面,即可看到新增的自定义字段,提交后数据会自动存储到自定义表中
额外提示
- 若使用Moodle 3.7及以上版本,也可以直接利用核心的自定义字段功能(无需编写插件):进入「站点管理 -> 自定义字段 -> 课程分类」即可添加字段,这种方式更轻量化
- 如需添加复杂字段类型(如文件上传、多选框),直接在
definition()方法中调用对应表单元素API即可
内容的提问来源于stack exchange,提问作者Hussam Aj
相关产品推荐
相关产品推荐

