事件与监听器

Chamilo 使用 Symfony 的事件系统来实现组件之间的解耦通信。

事件监听器

Chamilo 使用两个监听器位置:

  • src/CoreBundle/EventListener/ — Symfony 内核/HTTP 监听器(请求、响应、异常、登录/登出、课程/会话访问等)。示例:CidReqListenerCourseAccessListenerLoginSuccessHandlerLogoutListenerExceptionListenerResourceDoctrineListener

  • src/CoreBundle/Entity/Listener/ — 附加到特定实体的 Doctrine 实体监听器。示例:ResourceNodeListenerCourseListenerSessionListenerLanguageListenerUserListenerMessageListener

根据您需要响应的内容选择合适的位置:HTTP 管道事件放在 EventListener/ 中;实体生命周期钩子放在 Entity/Listener/ 中。

事件订阅者

位于 src/CoreBundle/EventSubscriber/

事件订阅者可以监听多个事件:

  • 安全订阅者 — 处理登录/登出事件,追踪登录尝试

  • API 订阅者 — 对 API 请求进行前/后处理

  • Doctrine 订阅者 — 响应实体生命周期事件

Doctrine 生命周期事件

实体使用 #[ORM\HasLifecycleCallbacks] 来处理数据库级别的事件:

创建自定义监听器

要添加自定义行为:

  1. 在适当的 bundle 中创建监听器/订阅者类

  2. 在服务配置中将其标记为事件监听器或订阅者

  3. 实现处理方法

关键事件

事件
触发时机

kernel.request

每次 HTTP 请求

kernel.response

发送 HTTP 响应之前

security.interactive_login

用户登录时

doctrine.prePersist

实体首次保存之前

doctrine.postUpdate

实体更新之后

Chamilo 特定事件

这些事件由 Chamilo 自身的代码触发,是插件的主要集成点。常量定义在 Chamilo\CoreBundle\Event\Events 中。

常量
事件字符串
触发时机

Events::COURSE_CREATED

chamilo.event.course_created

课程创建后

Events::COURSE_ACCESS_CHECK

chamilo.course_access_check

用户访问课程之前

Events::COURSE_USER_SUBSCRIPTION_CHECK

chamilo.event.course_user_subscription_check

用户注册课程之前

Events::SESSION_RESUBSCRIPTION

chamilo.event.session_resubscription

用户尝试重新订阅会话时

Events::LOGIN_CREDENTIALS_CHECKED

chamilo.event.login_credentials_checked

登录凭据验证后

Events::LOGIN_CONDITION_CHECKED

chamilo.event.login_condition_checked

额外登录条件检查后

Events::DOCUMENT_ACTION

chamilo.event.document_action

文档工具栏渲染时

Events::DOCUMENT_ITEM_ACTION

chamilo.event.document_item_action

每个文件的操作按钮渲染时

Events::DOCUMENT_ITEM_VIEW

chamilo.event.document_item_view

文档打开查看时

Events::EXERCISE_REPORT_ACTION

chamilo.event.exercise_report_action

练习报告页面渲染操作链接时

Events::EXERCISE_ENDED

chamilo.event.exercise_ended

学习者提交练习后

Events::EXERCISE_QUESTION_ANSWERED

chamilo.event.question_answered

每个问题回答后

Events::LP_CREATED

chamilo.event.learning_path_created

学习路径创建后

Events::LP_ITEM_VIEWED

chamilo.event.learning_path_item_viewed

学习者打开学习路径项目时

Events::LP_ENDED

chamilo.event.learning_path_ended

学习者完成学习路径后

Events::ADMIN_BLOCK_DISPLAYED

chamilo.event.admin_block_displayed

管理员仪表板构建块列表时

Events::USER_CREATED

chamilo.event.user_created

用户账户创建后

Events::USER_UPDATED

chamilo.event.user_updated

用户账户更新后

Events::USER_DELETED

chamilo.event.user_deleted

用户账户删除后

Events::PORTFOLIO_ITEM_ADDED

chamilo.event.portfolio_item_added

作品集项目创建后

Events::NOTIFICATION_CONTENT_FORMATTED

chamilo_hook_event.notification_content

通知内容格式化时

插件示例:在文档查看器中添加按钮

本节将介绍如何通过事件订阅者让插件在现有的 Chamilo 页面中注入一个按钮,而无需修改核心代码。

场景

一个名为 MyViewer 的插件希望在课程文件管理器中的每个文档旁边添加一个“在 MyViewer 中打开”按钮。相关事件是 Events::DOCUMENT_ITEM_VIEW,由 Chamilo 在文档即将显示时触发,携带 CDocument 实体和一个可变的链接列表。

插件目录结构

主插件类 (src/MyViewerPlugin.php)

Plugin 基类提供了 isEnabled()get($settingKey) 以及用于安装课程工具和设置的辅助方法。单例模式(static $instance)是 Chamilo 的标准约定,因为插件类也会在 Symfony 容器之外(在旧版 PHP 页面中)被实例化。

事件订阅者 (src/EventSubscriber/MyViewerEventSubscriber.php)

addLink() 将 HTML 添加到数组中,Chamilo 的文档视图模板会将其与内置的“下载”和“预览”操作一起渲染。订阅者从不修改 Chamilo 核心文件。

注册

无需手动注册服务。Chamilo 的 config/services.yaml 全局启用了 Symfony 的 autoconfigure 标志,该标志会自动将任何实现 EventSubscriberInterface 的类标记为 kernel.event_subscriber。只要插件目录被加载(通过 Composer's classmap 或 PSR-4 自动加载),Symfony 会在下一次缓存清除时自动识别订阅者。

事件数据流转方式

多个插件可以独立订阅同一事件;每个插件都会向共享数据中添加内容,而无需了解其他插件。执行顺序遵循 Symfony 的优先级系统——如果顺序重要,可以在 getSubscribedEvents() 中将优先级整数作为处理程序元组的第二个元素传递:

最后更新于

这有帮助吗?