其他
在 Hyvä CMS 中创建自定义字段类型与字段处理器时使用…
为 Hyvä CMS 组件扩展自定义字段类型或字段处理器(含基础输入、内联增强控件、模态选择器)时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 39/100 ×0.15
适用场景
在 Hyvä CMS 中创建自定义字段类特定
解决思路
- 对于需要在开发环境内运行的命令(如 bin/magento),使用 hyva-exec-shell-cmd 技能检测环境并确定适当的命令包装器。
- 如果 prompt 未指定创建位置,确定是在新模块还是现有模块中创建自定义字段类型。
- 新模块:使用 hyva-create-module 技能,dependencies 设为 Hyva_CmsBase 和 Hyva_CmsLiveviewEditor,composer_require 设为 hyva-themes/commerce-module-cms 的 ^1.0 版本。
- 现有模块:验证 etc/module.xml 中包含 Hyva_CmsBase 和 Hyva_CmsLiveviewEditor,composer.json 中包含 hyva-themes/commerce-module-cms,如有缺失则添加。
- 收集字段类型名称(小写标识符,如 date_range、product_selector、color_picker)。
- 收集字段用途(收集什么数据)。
- 确定 UI 模式:Basic field,简单输入带验证(日期选择器、模式输入、增强文本字段)。
- 确定 UI 模式:Inline handler,字段区域内增强控件(可搜索下拉、颜色选择器)。
- 确定 UI 模式:Modal handler,独立对话框用于复杂选择(产品选择器、链接构建器、媒体库)。
- 收集数据结构(简单字符串、JSON 对象、数组)。
- 收集验证要求(模式、必填、自定义规则)。
- 选择 Pattern A:Basic Custom Field Type,用于简单输入带自定义 HTML5 验证或专用输入控件;单个模板文件;无独立 handler modal;例:日期范围选择器、自定义模式验证、滑块输入。
- 选择 Pattern B:Inline Field Handler,用于增强控件保留在字段区域;单个模板文件带 Alpine.js 组件;无独立 handler modal;例:可搜索下拉、带色板的颜色选择器。
- 选择 Pattern C:Modal-Based Field Handler,用于需要更多空间的复杂选择界面;字段模板(显示选择 + 触发按钮);Handler modal 模板(独立对话框完整 UI);为 handler 注册 layout XML;例:产品选择器、链接配置、媒体库。
- 参考 references/handler-patterns.md 获取每种类型的详细实现模式和代码示例。
- 在 view/adminhtml/templates/field-types/[field-type-name].phtml 创建字段模板。
- 字段模板必需元素:字段容器 ID 为 field-container-{uid}_{fieldName}。
- 字段模板必需元素:输入元素 name 为 {uid}_{fieldName}。
- 字段模板必需元素:验证消息容器为 validation-messages-{uid}_{fieldName}。
- 字段模板必需元素:值变更时调用 updateWireField() 或 updateField()。
- 字段模板必需元素:通过 $magewire->errors 处理错误状态。
- 字段模板必需元素:字段值使用 null 合并 $block->getData('value') ?? '',不要使用类型转换。
- 使用 assets/templates/ 中适当模板:basic-field.phtml.tpl(基础自定义字段类型)、inline-handler.phtml.tpl(内联增强控件)、modal-field.phtml.tpl(模态 handler 字段模板)。
- 参考 references/template-requirements.md 获取详细模板要求和模式。
- 仅模态 handler:在 view/adminhtml/templates/handlers/[handler-name]-handler.phtml 创建 handler 模板。
- Handler modal 结构:使用 <dialog> 元素带 Alpine.js 组件和 open:flex 类(不是静态 flex)。
- Handler modal 结构:监听来自字段模板的初始化事件。
- Handler modal 结构:实现选择 UI(搜索、过滤器、网格等)。
- Handler modal 结构:保存时派发 editor-change 事件。
- 使用 assets/templates/modal-handler.phtml.tpl 作为起点。
- 参考 references/handler-communication.md 获取事件协议和数据交换模式。
- 在 etc/adminhtml/di.xml 添加注册:type name 为 Hyva\CmsLiveviewEditor\Model\CustomField,arguments 中 customTypes 数组项名为 [field_type_name],type 为 string,值为 [Vendor]_[Module]::field-types/[field-type-name].phtml。
- 仅模态 handler:创建或更新 view/adminhtml/layout/liveview_editor.xml,在 before.body.end 容器中添加 block name 为 [handler_name]_handler,template 为 [Vendor]_[Module]::handlers/[handler-name]-handler.phtml。
- 注意:内联 handler 不需要 layout XML 注册。
- 提供在 components.json 中使用自定义字段类型的示例,包含 type 为 custom_type、custom_type 为 [field_type_name]、label、attributes(如 required、pattern)。
- 在实现字段模板时,阅读 references/template-requirements.md 以确保与 CMS 编辑器正确集成。
- 在选择实现模式和编写模板代码时,阅读 references/handler-patterns.md。
- 在实现 handler modals 以理解通信协议时,阅读 references/handler-communication.md。
- 在寻找实现示例或可复制模式时,阅读 references/built-in-handlers.md。
- 使用 assets/templates/basic-field.phtml.tpl 时填充占位符:{{FIELD_TYPE_NAME}}、{{FIELD_INPUTS}}、{{VALIDATION_LOGIC}}。
- 使用 assets/templates/inline-handler.phtml.tpl 时填充占位符:{{HANDLER_NAME}}、{{HANDLER_LOGIC}}、{{HANDLER_UI}}。
- 使用 assets/templates/modal-field.phtml.tpl 时填充占位符:{{EVENT_NAME}}、{{BUTTON_LABEL}}、{{DISPLAY_VALUE}}。
- 使用 assets/templates/modal-handler.phtml.tpl 时填充占位符:{{HANDLER_NAME}}、{{MODAL_TITLE}}、{{SELECTION_UI}}、{{SAVE_LOGIC}}。
- 核心要求:所有自定义字段类型必须遵循必需标记模式(容器 ID、输入 name、验证消息)。
- 核心要求:模态 handler 需要 layout XML 注册;内联 handler 不需要。
- 核心要求:通过 $filteredAttributes 应用 HTML5 验证属性以实现自动验证。
- 核心要求:如果使用自定义 Alpine 组件,保持输入字段在组件外部,并通过原生 JS 更新。
- 核心要求:参考 Hyva_CmsLiveviewEditor::page/js/ 中的内置 handler 以获取已验证模式。
- 事件命名约定:使用 toggle-{type}-select 模式;正确示例:toggle-product-select、toggle-link-select、toggle-category-select;错误示例:toggle-product-handler、toggle-link-handler。
- Handler 函数命名:使用 init{Type}Select() 模式;示例:initProductSelect()、initLinkSelect()、initCategorySelect()。
- 字段值更新方法:默认使用 updateWireField(Products、Link、Category handlers),通过 Magewire 触发立即服务器端验证,保持组件状态同步。
- 字段值更新方法:专用场景使用 updateField(Image handler、防抖输入如颜色、范围),更新预览而不进行服务器往返,延迟验证直到保存。
- JSON 编码模式:所有复杂数据(数组、对象)必须 JSON 编码;字段模板中使用 $escaper->escapeHtmlAttr(json_encode($fieldValue));Handler 初始化中使用 JSON.parse(fieldValue);@change 中使用 updateWireField(..., JSON.parse($event.target.value))。
- 兼容 Livewire:可搜索选择使用 wire:ignore 包装,如 <div wire:ignore> 内放 x-data='initSearchableSelect(...)' 的 Alpine 组件。
- 即使内联 handler 也可能有独立函数文件:字段模板 liveview/field-types/searchable_select.phtml,Handler 函数 page/js/searchable-select-handler.phtml。
- Icons View Model:用于 UI 元素,使用 $icons = $viewModels->require(Icons::class); 并调用 $icons->trashHtml('', 22, 22)。
- FieldTypes View Model:用于属性过滤,使用 $fieldTypes = $viewModels->require(FieldTypes::class); 调用 getDefinedFieldAttributes($attributes) 或 getAttributesByKeys($attributes, ['required', 'data-required']) 得到 $filteredAttributes。
- 关键:Handler modals 必须使用 before.body.end 容器,正确为 <referenceContainer name='before.body.end'>,错误为 <referenceContainer name='content'>;before.body.end 确保 handler modal 在页面主体末尾加载,这是正确 Alpine.js 初始化和模态功能所必需的。
- 关键:绝不要对字段值使用类型转换,始终使用 null 合并运算符;正确:$fieldValue = $block->getData('value') ?? ''; 错误:$fieldValue = (string) $block->getData('value'); 类型转换 (string) 在值为 null 时会失败,导致 PHP 错误;字符串值使用 ?? '',数组值使用 ?? [],或适合数据类型的默认值;参考内置字段类型如 category.phtml 使用 ?? [] 模式。
- 关键:Handler modals 必须使用 open:flex 而不是静态 flex 类;正确:<dialog class='... open:flex flex-col'>;错误:<dialog class='... flex flex-col'>(模态始终可见);open: 前缀仅在对话框打开时应用样式(原生 HTML dialog 状态);参考内置 handler 如 category-handler.phtml 使用 open:flex flex-col。
- 关键:对于存储 JSON/数组数据的字段,处理数组和字符串两种类型;字段值可能返回已解码数组或 JSON 字符串(取决于存储/上下文);正确模式:$data = ['default' => 'structure']; if ($fieldValue) { if (is_array($fieldValue)) { $data = $fieldValue; } elseif (is_string($fieldValue)) { $decoded = json_decode($fieldValue, true); if (is_array($decoded)) { $data = $decoded; } } };输出到 hidden input 时始终确保是 JSON 字符串:$fieldValueJson = is_array($fieldValue) ? json_encode($fieldValue) : $fieldValue;;错误:json_decode($fieldValue) 未经类型检查(如果值已是数组会失败);错误:在 value 属性中直接使用数组而未先 JSON 编码。
适用边界 · 注意事项
- 不要用于 Hyvä CMS 之外的通用表单或 UI 工作。