关于 craftcms
craftcms 是面向开发者的参考技能,指导如何通过插件、模块、自定义元素和字段类型及后端集成扩展 Craft CMS 5。内容按任务组织,涵盖 Craft API 和常见实现陷阱。
主要功能
- 01插件与模块开发指导
- 02自定义元素和字段类型
- 03控制器、迁移与事件
- 04控制面板及后端集成
- 05按任务选择参考资料
- 06Craft 实现中的常见问题
适用场景
- 01构建自定义元素类型或字段类型
- 02添加 Webhook 端点或队列任务
- 03创建插件设置页或仪表板组件
- 04排查 Craft 配置与迁移行为
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ michtio/ craftcms-claude-skills --skill craftcms安装后在 Claude Code 中输入/craftcms确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/architecture.mdcaching.mdconditions.mdconfig-app.mdconfig-bootstrap.mdconfig-general-extended.mdconfig-general.mdconsole-commands.mdcontrollers.mdcp-components.mdcp-ui-patterns.mdcp.mddebugging.mddeployment.mddrafts-revisions.mdelement-authorization.mdelement-index.mdelements.mdemail.mdevents.mdfield-types-custom.mdfields.mdgraphql.mdidentity-protocols.mdmigrations.mdpermissions.mdplugin-vite.mdquality.mdqueue-jobs.mdsessions-and-auth.md详细介绍
Craft CMS 5 — 扩展(插件与模块)
通过插件和模块扩展 Craft CMS 5 的参考指南。涵盖从元素和服务到控制器、迁移、字段和事件的所有内容。
此技能适用于 Craft 的扩展,包括构建插件、模块、自定义元素类型、字段类型和后台集成。有关网站/平台开发(内容建模、区块、条目类型、Twig 模板、插件选择),请参阅 craft-site 技能。
配套技能 — 始终一并加载
触发此技能时,还需加载:
craft-php-guidelines— PHPDoc 标准、章节标题、命名约定、类组织、ECS/PHPStan 和验证清单。编写任何 PHP 代码时都必须加载。ddev— 所有命令均通过 DDEV 运行。运行 ECS、PHPStan、脚手架和测试时都必须加载。craft-garnish— 处理 CP JavaScript、资源包或交互式 CP 组件时加载。涵盖 Garnish 的类系统、UI 小部件(Modal、HUD、DisclosureMenu、Select)、拖动系统以及 Craft.* JS 类模式。craft-pest— 编写、运行、修复或审查测试时加载。涵盖markhuot/craft-pest-core测试框架、数据库隔离(其回滚为选择启用,环境变量覆盖受当前工作目录限制——二者都会导致对开发数据库的写入悄无声息地发生)、工厂、HTTP/队列/数据库断言以及 CI 测试任务。craft-cloud— 项目托管在 Craft Cloud 上时加载(通过仓库根目录的craft-cloud.yaml或composer.json中的craftcms/cloud检测)。处理插件的 Cloud 兼容性约束时必须加载,包括App::isEphemeral()守卫、资源包 CDN 发布、队列任务 15 分钟时限、使用csrfInput()函数而非直接输出令牌,以及cloud/up部署生命周期事件。
文档
- 扩展指南:https://craftcms.com/docs/5.x/extend/
- 类参考:https://docs.craftcms.com/api/v5/
- 生成器:https://craftcms.com/docs/5.x/extend/generator.html
参考文件未包含足够细节时,请对具体文档页面使用 WebFetch。
常见陷阱(跨领域)
- 始终在
beforePrepare()中使用addSelect()——这是 Craft 的惯例;多个扩展共同添加列时,它也能安全地累加。 - 队列工作进程在主站点上下文中运行——跨站点查询请使用
->site('*')。 - 在
getConfig()中包含id——项目配置使用 UID,从不使用数据库 ID。 - 不要在模型或控制器中编写业务逻辑——逻辑应放在服务中。
- 模块需要手动注册模板根目录、翻译和
controllerNamespace——没有任何内容会自动注册。 - 在元素/查询中使用
DateTimeHelper,在服务中使用Carbon——不要在同一个类中混用。 - 不要在 CP URL 中硬编码
/admin——cpTrigger可配置。PHP 中使用UrlHelper::cpUrl(),Twig 中使用cpUrl()。 - 在拆分设置页面上,直接将
$request->getBodyParams()传给savePluginSettings()——只有已提交的键会被保存,其他设置会悄无声息地丢失。请先加载完整的设置模型,更新属性,然后保存。 - 将路由或查询参数命名为
token——这会与 Craft 保留的tokenParam冲突,请求会在控制器运行前被拒绝并返回 400。请参阅controllers.md(保留的请求参数)。 - 插件
templates/目录中任何未以下划线开头的模板都可直接通过 CP 路由访问,绕过控制器的beforeAction()限制。除非模板有意作为直接路由,否则都应以下划线开头。请参阅cp.md(CP 模板路由会绕过控制器)。
参考文件
根据任务阅读相关参考文件。通常需要同时参考多个文件。 任务示例:
- “构建自定义元素类型” → 阅读
elements.md(先看 Architecture 部分)+element-index.md+fields.md+migrations.md+cp.md - “构建分层/树状元素类型” → 阅读
elements.md(Architecture:One Element Class with Native Structure) - “添加 webhook 端点” → 阅读
controllers.md+events.md - “创建一个用于同步元素的队列任务” → 阅读
queue-jobs.md+elements.md+debugging.md - “添加带表单字段的设置页面” → 阅读
controllers.md+cp.md+architecture.md - “注册自定义字段类型” → 阅读
fields.md+events.md - “修复 PHPStan 错误” → 阅读
quality.md - “添加仪表板小组件” → 阅读
cp-components.md(Dashboard Widgets)+events.md(Widget Types 部分) - “为插件用户公开模板变量” → 阅读
events.md(Twig Extensions 部分) - “为条目附加自定义方法” → 阅读
events.md(Behaviors 部分) - “注册自定义元素或字段类型” → 阅读
events.md(Registration Pattern → Registration scope — never gate by request context) - “已删除的自定义元素永远不会被删除/垃圾回收未清理/elements 表中的行不断堆积” → 阅读
events.md(Registration Pattern → Registration scope) - “构建 CP 工具页面” → 阅读
cp-components.md(Utility Pages)+events.md(Utilities 部分) - “为插件的 CP 资源配置 Vite” → 阅读
plugin-vite.md+ 加载craft-garnishskill - “为 CP 页面添加拖动排序或交互式 JS” → 加载
craft-garnishskill - “为自定义字段类型编写 CP JavaScript” → 阅读
fields.md+ 加载craft-garnishskill - “构建无头 Craft API” → 阅读
graphql.md+ 加载craft-siteskill 以查阅headless.md - “为 Next.js 前端配置预览” → 加载
craft-siteskill 以查阅headless.md - “为插件设置 Pest 测试” → 加载
craft-pestskill →isolation.md - “为控制器操作编写测试” → 加载
craft-pestskill →patterns.md - “测试正在写入我的开发数据库/创建了数千个多余元素” → 加载
craft-pestskill →isolation.md - “通过代码创建或删除站点(导入器、配置命令、fixture)” → 阅读
architecture.md(Creating or deleting sites at runtime) - “创建站点后,元素查询不再按 siteId 筛选” → 阅读
architecture.md(Creating or deleting sites at runtime —refreshSites()不会使读取变体查询失效) - “删除站点后,分区/类别组仍引用该站点” → 阅读
architecture.md(Creating or deleting sites at runtime —deleteSite()的清理与记忆化服务缓存) - “将记录的 dateUpdated 与截止时间比较/‘自某时起更改’筛选相差数小时” → 阅读
architecture.md(Those strings are naive UTC) - “将 ActiveRecord 中的 datetime 列读入模型” → 阅读
architecture.md(Record-to-Model Hydration Boundary) - “我的元素查询使用 ['like', ...] 后没有返回任何结果” → 阅读
architecture.md(Element-query param setters don't take Yii operator tuples) - “按标题/slug 前缀匹配元素” → 阅读
architecture.md(Element-query param setters don't take Yii operator tuples) - “配置 Redis 用于缓存和会话” → 阅读
config-app.md - “将 PHP 会话存储在数据库中(负载均衡器、没有 Redis)” → 阅读
config-app.md(Session Component —craft\web\DbSession、setup/php-session-table) - “为生产环境设置环境变量” → 阅读
config-bootstrap.md - “查找 GeneralConfig 设置” → 阅读
config-general.md - “在插件代码中读取配置值(App::env、parseEnv、GeneralConfig)” → 阅读
config-bootstrap.md+config-general.md - “在插件代码中检查 allowAdminChanges 是否已启用” → 阅读
config-general.md+cp.md(Read-Only Mode) - “在插件设置中解析环境变量($MY_API_KEY)” → 阅读
config-bootstrap.md(App::parseEnv) - “了解 CRAFT_* 环境变量约定” → 阅读
config-bootstrap.md - “配置邮件传输/SMTP” → 阅读
config-app.md - “设置自定义 URL 路由” → 阅读
config-bootstrap.md - “配置搜索以查找较短的单词” → 阅读
config-app.md - “设置 GraphQL 令牌和架构” → 阅读
graphql.md+config-general.md - “升级到 Craft 5.11 后,GraphQL 的
author/uploader字段消失了” → 阅读graphql.md(Craft 5.11 Additions — “Query for users” 范围) - “为高流量网站设置缓存” → 阅读
caching.md - “为我的插件注册自定义权限” → 阅读
permissions.md - “在模板中检查用户权限” → 阅读
permissions.md - “设置插件版本/功能门控” → 阅读
architecture.md(Plugin Editions 部分) - “构建流式渲染构建器/craft.plugin.widget().render()” → 阅读
architecture.md(Render builders:属性合并、选项允许列表) - “网站无法覆盖插件的前端 CSS/插件样式优先生效” → 阅读
architecture.md(插件注册的 CSS 在网站样式表之后加载) - “插件 JS 在随附模板中有效,在用户编写的模板中却无效” → 阅读
architecture.md(JS 与标记的契约是公共 API) - “从注册表/生成器输出生成文档/架构/类型,但不同安装或版本的输出不一致” → 阅读
quality.md(Generated Artifacts Must Not Read Runtime Registries) - “发布版本/打标签/Packagist 未提供新版本” → 加载
craft-plugin-releaseskill - “删除站点后,插件中按站点存储的行仍然存在” → 阅读
architecture.md(Site deletion is a soft delete) - “缓存了 false/缓存返回 false,我无法判断是否未命中” → 阅读
caching.md(Data Caching → boolean sentinel idiom) - “插件/运维设置(阈值、通知路由、工作流映射)应放在哪里——项目配置还是数据库?” → 阅读
architecture.md(Settings belong in project config) - “阈值是否应该只存在数据库中,以避免跨环境变更?” → 阅读
architecture.md(Settings belong in project config)——这是一个需要纠正的误解 - “将插件从 Craft 4 升级到 5” → 阅读
quality.md(Rector 部分) - “为 Craft 插件设置 CI” → 阅读
quality.md(CI/CD Integration 部分) - “在迁移中创建分区或字段” → 阅读
migrations.md(Content Migrations 部分) - “安装失败并提示 ‘Too many keys specified; max 64 keys allowed’/重复索引不断堆积” → 阅读
migrations.md(可重复运行的索引创建与 MySQL 的 64 个键上限) - “运行模块的迁移/--track=module: 被拒绝/库中提供的模块架构从未应用” → 阅读
migrations.md(模块和库中提供的模块没有 CLI 跟踪标记) - “修复插件升级后错误存储的项目配置值” → 阅读
migrations.md(不要在迁移中调用 ProjectConfig::flush()) - “以编程方式解除用户停用/恢复用户/解除停用后用户仍无法登录” → 阅读
elements.md(getStatus() 会隐藏并存的状态) - “我需要重写 settingsAttributes() 吗?” → 阅读
field-types-custom.md(settingsAttributes() 实际包含的内容) - “设置数据库只读副本” → 阅读
config-app.md(Database Replicas 部分) - “在 app.php 中注册模块” → 阅读
config-app.md(Module Registration 部分) - “创建自定义验证器” → 阅读
architecture.md(Custom Validators 部分) - “创建自定义文件系统类型” → 阅读
events.md(Filesystem Types 部分) - “为元素索引构建自定义条件规则” → 阅读
cp-ui-patterns.md(Condition Builders) - “构建三态/继承/关闭控件” → 阅读
cp-ui-patterns.md(Tri-State Inheritance Controls) - “为插件添加带标签页的设置页面” → 阅读
cp.md(Tabbed Settings Pages) - “插件支持 config/.php 覆盖——设置页面应如何显示?” → 阅读
cp.md(Settings Pages → Config-file overrides: warn on the field, don't disable it) - “设置已保存,但没有任何变化/配置文件悄悄覆盖了设置” → 阅读
cp.md(Settings Pages → Config-file overrides) - “为什么我的 URL 标签页无法导航/标签页与独立页面的侧边栏导航该如何选择?” → 阅读
cp.md(Tabs switch panes — they never navigate) - “构建 CP 索引/列表屏幕:列、复制小标签、行操作” → 阅读
cp-ui-patterns.md(Index-screen column scheme)+cp-components.md(VueAdminTable) - “VueAdminTable 裁切标题/介绍文字和 New 按钮该放在哪里?” → 阅读
cp-components.md(VueAdminTable → sole pane content) - “工具图标不显示/icon() 路径” → 阅读
cp-components.md(Utility Pages) - “在布局元素上隐藏可见性/可编辑性条件构建器” → 阅读
fields.md(Suppressing the condition builders) - “在字段上显示‘覆盖全局设置’警告” → 阅读
cp-ui-patterns.md(Field Warning Parameter) - “Craft CP 使用哪些 CSS 变量/设计令牌?” → 阅读
cp-ui-patterns.md(Craft CSS Custom Properties — 颜色/状态/间距/圆角/控件/焦点/字体令牌) - “布尔设置应使用 Lightswitch 还是复选框?” → 阅读
cp.md(Form Macros Reference → Lightswitch vs checkbox) - “渲染复制文本/API 密钥/webhook URL 字段” → 阅读
cp.md(Form Macros Reference → copytextField) - “Save/Delete/Add 按钮应使用哪个按钮类?” → 阅读
cp.md(Form Macros Reference → Button modifier classes) - “向 CP 面板添加内部侧边栏子导航” → 阅读
cp.md(Form Macros Reference → Inner sidebar navigation) - “向设置页面添加可内联编辑的表格” → 阅读
cp-components.md(Editable Table Field) - “在 CP 中显示模态框或确认对话框(Craft.confirm() 并不存在)” → 阅读
cp-components.md(Modals)+ 加载craft-garnishskill 以实现行为 - “关系字段有哪些视图模式/previewMode/maxRelations?” → 阅读
element-index.md(Relation Field Display/Props) - “向字段布局添加 Tip/Heading/内置 UI 元素” → 阅读
fields.md(Field-Layout UI Elements Reference) - “向元素编辑屏幕的侧边栏添加面板” → 阅读
cp-ui-patterns.md(Element Edit Screen)+elements.md(EVENT_DEFINE_SIDEBAR_HTML) - “向元素顶部工具栏添加拆分按钮” → 阅读
cp-ui-patterns.md(Element Edit Screen → toolbar split button)+elements.md(EVENT_DEFINE_ADDITIONAL_BUTTONS) - “为什么我的侧边栏面板渲染后没有样式/显示异常?” → 阅读
cp-ui-patterns.md(Element Edit Screen →.meta与.meta read-only) - “在自定义元素上重写 metaFieldsHtml()” → 阅读
cp-ui-patterns.md(Element Edit Screen → metaFieldsHtml override) - “设置代码质量的提交前钩子” → 阅读
quality.md(Pre-Commit Hooks 部分) - “按用户组限制元素访问” → 阅读
element-authorization.md+permissions.md - “按权限限定 CP 元素索引” → 阅读
element-authorization.md(Layer 3: Query Scoping) - “为自定义元素添加授权事件” → 阅读
element-authorization.md+elements.md - “为安全插件构建纵深防御” → 阅读
element-authorization.md(Defense Patterns) - “在所有设备上强制用户登出” → 阅读
sessions-and-auth.md(Plugin Patterns) - “了解 Craft 会话的工作方式” → 阅读
sessions-and-auth.md - “实现必须重置密码的功能” → 阅读
sessions-and-auth.md(passwordResetRequired Gap) - “向 Users 元素索引添加一列” → 阅读
element-index.md(Extending Element Indexes via Events) - “向元素索引添加批量操作” → 阅读
element-index.md(Adding a custom bulk action) - “向每个元素编辑屏幕的菜单添加操作” → 阅读
element-index.md(Per-Element Edit-Screen Action Menu) - “在表格列中渲染状态标签” → 阅读
element-index.md(Status Pills in Table Attributes) - “向元素索引添加自定义侧边栏来源” → 阅读
element-index.md(Adding a sidebar source) - “构建自定义字段类型” → 阅读
field-types-custom.md+fields.md - “构建关系字段类型” → 阅读
field-types-custom.md(Relation Fields) - “向条目索引添加条件规则” → 阅读
conditions.md+element-index.md - “构建自定义条件规则” → 阅读
conditions.md - “从插件发送电子邮件” → 阅读
email.md - “注册自定义系统消息” → 阅读
email.md(Registering Custom System Messages) - “配置 SMTP 传输” → 阅读
config-app.md+email.md - “将 Craft CMS 部署到生产环境” → 阅读
deployment.md - “为 Craft 项目设置 CI/CD” → 阅读
deployment.md(CI/CD Patterns) - “零停机部署” → 阅读
deployment.md(Zero-Downtime) - “回滚失败的部署” → 阅读
deployment.md(Rollback Strategies) - “使用草稿和修订版本” → 阅读
drafts-revisions.md - “以编程方式创建草稿” → 阅读
drafts-revisions.md(Creating Drafts) - “在 afterSave 中跳过草稿的副作用” → 阅读
drafts-revisions.md(Plugin Considerations) - “向自定义元素添加生成字段” → 阅读
elements.md(Generated Fields) - “自定义元素显示为小标签或卡片时的外观” → 阅读
element-index.md(Element Display Modes) - “向用户编辑页面添加屏幕” → 阅读
elements.md(Extending User Edit Screens) - “当 allowAdminChanges 关闭时,将插件设置设为只读” → 阅读
cp.md(Read-Only Mode) - “向插件的设置页面添加标签页” → 阅读
cp.md(Settings Pages → With tabs or custom actions)。settingsHtml()仅支持单面板——标签页需要自定义控制器和直接扩展_layouts/cp的模板。 - “在插件自己的 CP 分区中渲染插件设置(而非全局设置/插件页面)” → 阅读
cp.md(Settings Pages → Keep settings inside the plugin's own CP section) - “让插件兼容 Cloud” → 加载
craft-cloudskill →plugin-development.md(临时文件系统、资源包限制、队列上限、CSRF 函数、无 Cookie 设计) - “将 Craft 项目部署到 Cloud” → 加载
craft-cloudskill →config-file.md+deploy-pipeline.md+extension.md - “将可自托管的 Craft 站点迁移到 Cloud” → 加载
craft-cloudskill →migration.md - “为什么插件在 Cloud 上写入文件时会无提示地失败?” → 加载
craft-cloudskill →plugin-development.md(临时文件系统)+extension.md(App::isEphemeral) - “构建 SSO/OIDC 登录或 SCIM 配置功能” → 阅读
identity-protocols.md+sessions-and-auth.md - “处理单点登出/logout_token/由提供方发起的取消配置” → 阅读
identity-protocols.md仅加载任务所需的参考文件——每个文件都会在每轮消耗输入令牌。 | 任务 | 阅读 | ~词元 | |------|------|--------:| | 元素核心:生命周期、查询、状态、授权、草稿、修订、传播、字段布局、用户编辑界面、事件 |references/elements.md| 8.4K | | 元素索引:来源、表格/卡片属性、状态标签、排序、条件、操作(批量操作和单元素操作菜单)、导出器、侧边栏、元数据、关系字段显示/属性(viewMode、previewMode、maxRelations)、通过事件扩展 |references/element-index.md| 6.1K | | 服务、模型、记录、项目配置(包括运行时站点创建/删除缓存)、MemoizableArray、事件、API 客户端、自定义验证器 |references/architecture.md| 7.4K | | 控制器:控制面板 CRUD、Webhook、API 端点、操作路由、授权 |references/controllers.md| 3.9K | | 控制面板模板、表单宏(包括 lightswitch 与 checkbox、copytext、money、按钮类)、设置页面、导航(包括内侧边栏导航)、权限、只读模式 |references/cp.md| 7.2K | | 控制面板组件:仪表板小组件、工具页面、滑出式编辑器、Ajax、可编辑表格、加载指示器、模态框(标记和遮罩)、警报 |references/cp-components.md| 1.8K | | 控制面板 UI 模式:三态控件、状态指示器、语义化 CSS 令牌(颜色/状态/间距/圆角/控件/焦点/字体)、条件构建器、资源包、元素编辑界面侧边栏面板和工具栏拆分按钮 |references/cp-ui-patterns.md| 3.4K | | 数据库迁移、Install.php、外键、索引、幂等性、部署 |references/migrations.md| 3.9K | | 队列作业、BaseJob、TTR、重试、进度、批量作业、站点上下文 |references/queue-jobs.md| 4.2K | | 控制台命令、参数、选项、进度条、输出辅助工具、重新保存操作 |references/console-commands.md| 6.0K | | 调试、性能、查询策略、性能分析、Xdebug、缓存、日志记录 |references/debugging.md| 4.6K | | PHPStan、ECS、代码审查清单 |references/quality.md| 3.5K | | 测试:指向craft-pest技能(Pest/craft-pest-core 在其中)+ Codeception 基础知识 |references/testing.md| 0.6K | | 字段类型、原生字段、BaseNativeField、字段布局元素(内置 Tip/Heading/LineBreak/HorizontalRule 参考)、FieldLayoutBehavior |references/fields.md| 3.6K | | 事件:注册、生命周期、命名约定、自定义事件、行为、Twig 扩展、实用工具、小组件、文件系统 |references/events.md| 4.4K | | GraphQL 类型、查询、变更、指令、架构组件、解析器 |references/graphql.md| 4.6K | | 插件 Vite:VitePluginService、控制面板资源包、HMR、TypeScript、控制面板中的 Vue |references/plugin-vite.md| 2.7K | | 无头与混合模式:headlessMode、GraphQL API、CORS、预览令牌、前端框架 | craft-site 技能references/headless.md| 3.4K | | GeneralConfig(系统、路由、安全、用户、会话、搜索、资源、图像) |references/config-general.md| 8.4K | | GeneralConfig(内容、模板、性能、垃圾回收、本地化、无头模式、GraphQL、无障碍) |references/config-general-extended.md| 7.2K | | 应用配置:缓存、会话、队列、互斥锁、邮件程序/SMTP、搜索、日志记录、CORS、数据库副本 |references/config-app.md| 5.5K | | 配置引导:环境变量、别名、优先级顺序、流式 API、custom.php、db.php、routes.php |references/config-bootstrap.md| 3.6K | | 缓存:模板缓存标签、数据缓存、静态缓存(Blitz)、CDN、分层策略、失效处理 |references/caching.md| 5.2K | | 权限:内置句柄、用户组、自定义注册、Twig/PHP 检查、授权事件 |references/permissions.md| 4.7K | | 元素授权:四层防御模型、授权事件、can*() 方法、查询范围限定 |references/element-authorization.md| 4.6K | | 会话与身份验证内部机制:双层会话模型、身份验证令牌、会话失效、提升权限的会话 |references/sessions-and-auth.md| 3.0K | | SSO/预配插件的身份协议:反向通道与正向通道注销、签名算法允许列表、issuer 与租户(hd 声明)、SCIM active:false 与 PATCH 顺序、厂商与 RFC 的差异 |references/identity-protocols.md| 1.3K | | 自定义字段类型:构建模式、值生命周期、设置、输入 HTML、验证、搜索、GraphQL |references/field-types-custom.md| 3.5K | | 条件框架:BaseCondition、ElementCondition、自定义条件规则、注册规则 |references/conditions.md| 2.3K | | 电子邮件系统:系统消息、自定义消息、以编程方式发送、模板、事件、测试 |references/email.md| 2.4K | | 部署:标准流水线、项目配置部署、零停机、CI/CD、回滚 |references/deployment.md| 2.5K | | 草稿与修订:草稿类型、临时草稿、自动保存、应用、合并、修订 |references/drafts-revisions.md| 2.5K |
插件与模块的区别
插件和模块采用相同的架构模式。两者在引导和注册方面有所不同:
| 功能 | 插件 | 模块 |
|---|---|---|
| CP 模板根目录 | 自动注册(按句柄) | 通过 EVENT_REGISTER_CP_TEMPLATE_ROOTS 手动注册 |
| 站点模板根目录 | 通过事件手动注册 | 相同——两者都需手动注册 |
| 翻译类别 | 自动注册(按句柄) | 在 init() 中手动注册 PhpMessageSource |
| 设置模型 | 内置 createSettingsModel() | 环境变量、配置文件或私有插件(_ 前缀) |
| 安装迁移 | migrations/Install.php | 仅限内容迁移 |
| 控制台命令 | 自动注册 controllerNamespace | 必须在 parent::init() 前设置,并且必须引导 |
| CP 导航区域 | $hasCpSection = true | EVENT_REGISTER_CP_NAV_ITEMS |
| 项目配置 | 设置会自动跟踪 | 仅手动调用 ProjectConfig::set() |
| 命名空间别名 | 通过 Composer 自动设置 | 必须调用 Craft::setAlias() |
模块模板根目录注册
use craft\events\RegisterTemplateRootsEvent;
use craft\web\View;
Event::on(View::class, View::EVENT_REGISTER_CP_TEMPLATE_ROOTS,
function(RegisterTemplateRootsEvent $event) {
$event->roots['my-module'] = __DIR__ . '/templates';
}
);
模块翻译注册
Craft::$app->i18n->translations['my-module'] = [
'class' => \craft\i18n\PhpMessageSource::class,
'sourceLanguage' => 'en',
'basePath' => __DIR__ . '/translations',
'allowOverrides' => true,
];
模块控制台命令注册
public function init()
{
Craft::setAlias('@mymodule', __DIR__);
if (Craft::$app->getRequest()->getIsConsoleRequest()) {
$this->controllerNamespace = 'modules\\mymodule\\console\\controllers';
} else {
$this->controllerNamespace = 'modules\\mymodule\\controllers';
}
parent::init(); // MUST come after setting controllerNamespace
}
必须在 config/app.php 中引导模块,才能发现其控制台命令。
评论
支持 Markdown