mcpField
H
hyva-cms-custom-field

hyva-cms-custom-field

github.com/hyva-themes开发85755 次安装13 周前更新
代码仓库

关于 hyva-cms-custom-field

为开发者提供创建 Hyvä CMS 自定义字段类型及字段处理器的技能,用于扩展编辑器输入控件。它引导选择基础字段、内联处理器或模态处理器,并生成模板和注册配置。

主要功能

  1. 01支持基础字段、内联和模态处理器
  2. 02生成字段及处理器模板
  3. 03配置字段类型注册
  4. 04为模态处理器添加布局注册
  5. 05提供字段使用示例

适用场景

  1. 01为编辑器添加颜色选择控件
  2. 02创建产品选择或链接配置模态框
  3. 03为自定义输入实现验证逻辑

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hyva-themes/hyva-ai-tools --skill hyva-cms-custom-field

安装后在 Claude Code 中输入/hyva-cms-custom-field确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/templates/
basic-field.phtml.tpl
inline-handler.phtml.tpl
modal-field.phtml.tpl
modal-handler.phtml.tpl
references/
built-in-handlers.md
handler-communication.md
handler-patterns.md
template-requirements.md

详细介绍

Hyvä CMS 自定义字段类型创建工具

概述

此技能指导如何为 Hyvä CMS 组件创建自定义字段类型和字段处理器。自定义字段类型扩展内置字段类型(文本、文本区域、选择框等),为 CMS 编辑器界面提供专用输入控件。

两种自定义字段:

  1. 基本自定义字段类型:可直接输入数据的自定义输入控件(例如日期范围、颜色选择器、自定义验证)
  2. 字段处理器:带有复杂交互的增强界面(例如带图片的产品选择器、可搜索下拉菜单、链接配置模态框)

**命令执行:**对于需要在开发环境中运行的命令(例如 bin/magento),请使用 hyva-exec-shell-cmd 技能检测环境并确定合适的命令包装器。

工作流

步骤 1:选择模块

如果提示中尚未指定,请确定要在哪个位置创建自定义字段类型:

选项 A:新建模块

使用 hyva-create-module 技能,并设置:

  • dependencies:["Hyva_CmsBase", "Hyva_CmsLiveviewEditor"]
  • composer_require:{"hyva-themes/commerce-module-cms": "^1.0"}

选项 B:现有模块

确认模块具有所需依赖项:

  • etc/module.xml 中包含 Hyva_CmsBase 和 Hyva_CmsLiveviewEditor
  • composer.json 中包含 hyva-themes/commerce-module-cms

如有缺失,请添加相应依赖项。

步骤 2:字段类型详情

收集有关自定义字段类型的信息:

  1. 字段类型名称(小写标识符,例如 date_range、product_selector、color_picker)
  2. 用途(它收集什么数据?)
  3. UI 模式:
    • 基本字段:带验证的简单输入(日期选择器、模式输入框、增强文本字段)
    • 内联处理器:在字段区域中显示的增强控件(可搜索下拉菜单、颜色选择器)
    • 模态框处理器:用于复杂选择的独立对话框(产品选择器、链接构建器、媒体库)
  4. 数据结构(简单字符串、JSON 对象、数组?)
  5. 验证要求(模式、必填、自定义规则?)
步骤 3:选择实现模式

根据步骤 2 中确定的 UI 模式:

模式 A:基本自定义字段类型

适用于需要自定义 HTML5 验证或专用输入控件的简单输入:

  • 单个字段模板文件
  • 无独立处理器模态框
  • 示例:日期范围选择器、自定义模式验证、滑块输入

模式 B:内联字段处理器

适用于保留在字段区域中的增强控件:

  • 带有 Alpine.js 组件的单个模板文件
  • 无独立处理器模态框
  • 示例:可搜索下拉选择框、带色板的颜色选择器

模式 C:基于模态框的字段处理器

适用于需要更大空间的复杂选择界面:

  • 字段模板(显示所选内容和触发按钮)
  • 处理器模态框模板(包含完整 UI 的独立对话框)
  • 用于注册处理器的布局 XML
  • 示例:产品选择器、链接配置、媒体库

有关每种类型的详细实现模式和代码示例,请参阅 references/handler-patterns.md。

步骤 4:生成字段模板

在 view/adminhtml/templates/field-types/[field-type-name].phtml 创建字段模板。

模板必需元素:

  1. 字段容器,且 ID 正确:field-container-{uid}_{fieldName}
  2. 名称为 {uid}_{fieldName} 的输入元素
  3. 验证消息容器:validation-messages-{uid}_{fieldName}
  4. 值更改时调用 updateWireField() 或 updateField()
  5. 通过 $magewire->errors 处理错误状态
  6. **重要:**使用空值合并运算符获取字段值:$block->getData('value') ?? ''(不要进行类型转换)

使用 assets/templates/ 中合适的模板:

  • basic-field.phtml.tpl - 基本自定义字段类型
  • inline-handler.phtml.tpl - 内联增强控件
  • modal-field.phtml.tpl - 模态框处理器字段模板

有关详细的模板要求和模式,请参阅 references/template-requirements.md。

步骤 5:生成处理器模态框(如需要)

仅对于基于模态框的处理器,在 view/adminhtml/templates/handlers/[handler-name]-handler.phtml 创建处理器模板。

处理器模态框结构:

  1. 使用 Alpine.js 组件和 open:flex 类的 <dialog> 元素(不要使用静态的 flex)
  2. 监听来自字段模板的初始化事件
  3. 实现选择界面(搜索、筛选、网格等)
  4. 保存时分发 editor-change 事件

以 assets/templates/modal-handler.phtml.tpl 为起始模板。

请参阅 references/handler-communication.md,了解事件协议和数据交换模式。

步骤 6:注册字段类型

在 etc/adminhtml/di.xml 中添加注册项:

<type name="Hyva\CmsLiveviewEditor\Model\CustomField">
    <arguments>
        <argument name="customTypes" xsi:type="array">
            <item name="[field_type_name]" xsi:type="string">
                [Vendor]_[Module]::field-types/[field-type-name].phtml
            </item>
        </argument>
    </arguments>
</type>
步骤 7:注册处理器模态框(如需要)

仅对于基于模态框的处理器,创建或更新 view/adminhtml/layout/liveview_editor.xml:

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="before.body.end">
            <block name="[handler_name]_handler"
                   template="[Vendor]_[Module]::handlers/[handler-name]-handler.phtml"/>
        </referenceContainer>
    </body>
</page>

注意: 内联处理器不需要在布局 XML 中注册。

步骤 8:使用示例

在 components.json 中提供自定义字段类型的使用示例:

{
    "my_component": {
        "label": "My Component",
        "content": {
            "[field_name]": {
                "type": "custom_type",
                "custom_type": "[field_type_name]",
                "label": "Field Label",
                "attributes": {
                    "required": true,
                    "pattern": ".*"
                }
            }
        }
    }
}

资源

references/template-requirements.md

自定义字段类型模板要求的完整参考:

  • 必需的标记模式和元素 ID
  • 字段容器结构
  • 验证消息容器
  • 字段值更新方法(updateWireField 与 updateField)
  • HTML5 验证属性
  • 错误状态处理

实现字段模板时请阅读此文件,以确保与 CMS 编辑器正确集成。

references/handler-patterns.md

三种自定义字段类型的实现模式:

  • 基础自定义字段类型(简单输入)
  • 内联字段处理器(增强控件)
  • 基于模态框的字段处理器(对话框选择)

每种模式都包含:

  • 完整代码示例
  • 各模式的适用场景
  • Alpine.js 组件结构
  • 数据流和状态管理

选择实现模式并编写模板代码时请阅读此文件。

references/handler-communication.md

字段处理器的事件协议和数据交换:

  • 初始化事件结构
  • 保存事件结构
  • 字段值编码和解码
  • 错误处理模式
  • 常见问题及解决方案

实现处理器模态框时请阅读此文件,以了解通信协议。

references/built-in-handlers.md

Hyvä CMS 内置字段处理器参考:

  • Product Handler(基于模态框,图片网格选择)
  • Link Handler(基于模态框,多类型链接配置)
  • Searchable Select(内联增强下拉菜单)

每种处理器都包含:

  • 在 Hyvä CMS 模块中的位置
  • 主要功能和模式
  • 使用示例
  • 可供研究实现模式的代码

查找实现示例或可复制的模式时请阅读此文件。

assets/templates/basic-field.phtml.tpl

带有自定义验证或输入控件的基础自定义字段类型模板。

占位符:

  • {{FIELD_TYPE_NAME}} - 自定义字段类型标识符
  • {{FIELD_INPUTS}} - 输入元素 HTML
  • {{VALIDATION_LOGIC}} - 自定义验证 JavaScript(可选)
assets/templates/inline-handler.phtml.tpl

内联增强控件模板(可搜索下拉菜单、颜色选择器等)。

占位符:

  • {{HANDLER_NAME}} - Alpine.js 组件名称
  • {{HANDLER_LOGIC}} - Alpine.js 组件实现
  • {{HANDLER_UI}} - 增强控件 HTML
assets/templates/modal-field.phtml.tpl

基于模态框的处理器字段模板(触发按钮 + 隐藏输入框)。

占位符:

  • {{EVENT_NAME}} - 要分发的自定义事件名称
  • {{BUTTON_LABEL}} - 按钮文本
  • {{DISPLAY_VALUE}} - 当前选项的显示内容
assets/templates/modal-handler.phtml.tpl

基于模态框的选择界面处理器模板。

占位符:

  • {{HANDLER_NAME}} - Alpine.js 组件名称
  • {{MODAL_TITLE}} - 对话框标题文本
  • {{SELECTION_UI}} - 选择界面 HTML
  • {{SAVE_LOGIC}} - 保存按钮逻辑

重要指南

核心要求
  1. 模板要求:所有自定义字段类型都必须遵循规定的标记模式(容器 ID、输入名称、验证消息)
  2. 处理器注册:模态框处理器需要在布局 XML 中注册;内联处理器无需注册
  3. 验证:通过 $filteredAttributes 应用 HTML5 验证属性,以实现自动验证
  4. Alpine 组件:如果使用自定义 Alpine 组件,请将输入字段置于组件之外,并通过原生 JavaScript 更新
  5. 内置示例:参考 Hyva_CmsLiveviewEditor::page/js/ 中的内置处理器,了解经过验证的模式
代码库中的准确模式

根据内置的 Hyvä CMS 处理器实现:

  1. 事件命名约定:使用 toggle-{type}-select 模式

    • ✅ 正确:toggle-product-select、toggle-link-select、toggle-category-select
    • ❌ 错误:toggle-product-handler、toggle-link-handler
  2. 处理器函数命名:使用 init{Type}Select() 模式

    • ✅ 示例:initProductSelect()、initLinkSelect()、initCategorySelect()
  3. 字段值更新方法:

    • 使用 updateWireField(默认):Products、Link、Category 处理器
      • 通过 Magewire 立即触发服务端验证
      • 保持组件状态同步
    • 使用 updateField(特定情况):Image 处理器、使用防抖的输入项(color、range)
      • 更新预览,但不进行服务器往返
      • 延迟到保存时再验证
  4. JSON 编码模式:所有复杂数据(数组、对象)都必须进行 JSON 编码

    // Field template
    value="<?= $escaper->escapeHtmlAttr(json_encode($fieldValue)) ?>"
    
    // Handler initialization
    const data = JSON.parse(fieldValue);
    
    // @change handler
    @change="updateWireField(..., JSON.parse($event.target.value))"
    
  5. 为兼容 Livewire 使用 wire:ignore:可搜索的选择框使用 wire:ignore 包装器

    <div wire:ignore>
        <div x-data="initSearchableSelect(...)">
            
        </div>
    </div>
    
  6. 单独的处理器文件:即使是内联处理器,也可能有单独的函数文件

    • 字段模板:liveview/field-types/searchable_select.phtml
    • 处理器函数:page/js/searchable-select-handler.phtml
  7. Icons 视图模型:用于 UI 元素

    /** @var Icons $icons */
    $icons = $viewModels->require(Icons::class);
    <?= /** @noEscape */ $icons->trashHtml('', 22, 22) ?>
    
  8. FieldTypes 视图模型:用于属性筛选

    /** @var FieldTypes $fieldTypes */
    $fieldTypes = $viewModels->require(FieldTypes::class);
    $filteredAttributes = $fieldTypes->getDefinedFieldAttributes($attributes);
    // Or for specific attributes:
    $filteredAttributes = $fieldTypes->getAttributesByKeys($attributes, ['required', 'data-required']);
    
  9. 关键:布局 XML referenceContainer:处理器模态框必须使用 before.body.end 容器

    • ✅ 正确:<referenceContainer name="before.body.end">
    • ❌ 错误:<referenceContainer name="content">
    • before.body.end 容器可确保处理器模态框在页面正文末尾加载,这是 Alpine.js 正常初始化和模态框功能正常运行的必要条件
  10. 关键:字段值类型处理:绝不要对字段值进行类型转换,始终使用 null 合并运算符

  • ✅ 正确:$fieldValue = $block->getData('value') ?? '';
  • ❌ 错误:$fieldValue = (string) $block->getData('value');
  • 值为 null 时,类型转换 (string) 会失败并导致 PHP 错误
  • 字符串值使用 ?? '',数组值使用 ?? [],其他数据类型则使用适当的默认值
  • 参考:请参见内置字段类型,例如使用 ?? [] 模式的 category.phtml
  1. 关键:对话框模态框类:处理器模态框必须使用 open:flex,不能使用静态的 flex 类
  • ✅ 正确:<dialog class="... open:flex flex-col">
  • ❌ 错误:<dialog class="... flex flex-col">(模态框始终可见)
  • open: 前缀仅在对话框打开时(原生 HTML 对话框状态)应用样式
  • 参考:请参见内置处理器,例如使用 open:flex flex-col 的 category-handler.phtml
  1. 关键:复杂数据类型处理:对于存储 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;
            }
        }
    }
    
    // 输出到隐藏输入框时,始终确保其为 JSON 字符串
    $fieldValueJson = is_array($fieldValue) ? json_encode($fieldValue) : $fieldValue;
    
  • ❌ 错误:未检查类型就使用 json_decode($fieldValue)(如果值已经是数组,则会失败)
  • ❌ 错误:未先进行 JSON 编码,就直接在 value 属性中使用数组

评论

支持 Markdown