关于 bagisto-attribute-development
用于修改 Bagisto 商品属性、属性族、选项和值的开发技能。它说明 EAV 存储模型,以及开发者编辑商品数据时必须遵循的语言和渠道规则。
主要功能
- 01说明 EAV 商品数据存储
- 02列出属性类型对应的值列
- 03讲解语言与渠道范围
- 04涵盖属性族、分组、选项和验证
- 05指导通过 Repository 修改数据
- 06说明刷新扁平索引的要求
适用场景
- 01新增或修改 Bagisto 商品属性
- 02排查跨语言或渠道缺失的值
- 03使用选项 ID 保存 select 值
- 04更新列表属性并重新索引商品
MCP 相关
这是开发技能,而非 MCP 服务。输入未说明 MCP 集成。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bagisto/ agent-skills --skill bagisto-attribute-development安装后在 Claude Code 中输入/bagisto-attribute-development确认已加载。
附带文件attributes.mdeav.md
详细介绍
属性开发
Bagisto 以 EAV(实体、属性、值)而非 products 上的列来存储产品数据。产品行几乎不存放任何内容;名称、价格、描述以及所有自定义字段都存放在 product_attribute_values 中,每个属性、每种语言区域和每个渠道对应一行。
Bagisto 中大多数错误都源于这个概念,因此在更改任何涉及产品数据的内容之前,值得先阅读 eav.md。
参考文件
| 文件 | 何时阅读 |
|---|---|
| eav.md | 值的存储与解析方式——列映射、作用域、平面索引 |
| attributes.md | 创建属性、属性族、分组、选项、验证和色板 |
结构
attribute_families a product type's whole form (e.g. "Default")
└── attribute_groups a tab/section within it (e.g. "General")
└── attributes a field (e.g. "name")
└── attribute_options for select, multiselect and checkbox
一个产品属于一个属性族,而该属性族决定了它拥有哪些属性。AttributeFamily::custom_attributes() 和 AttributeGroup::custom_attributes() 是用于遍历这些属性的关联关系。
列映射
属性的 type 决定 product_attribute_values 中哪一列存储其值:
| 类型 | 列 |
|---|---|
text、textarea、multiselect、checkbox、file、image | text_value |
price | float_value |
boolean | boolean_value |
select | integer_value |
date | date_value |
datetime | datetime_value |
此映射定义在 Attribute::$attributeTypeFields 中,模型会将解析后的名称公开为 $attribute->column_name。切勿猜测列名——应从属性中读取,否则 select 会悄悄写入 text_value,读取时却返回 null。
AttributeTypeEnum 是类型的权威列表;ValidationEnum(numeric、email、decimal、url、regex)和 SwatchTypeEnum(dropdown、color、image、text)则涵盖其余类型。
作用域:最常导致错误的两个标志
每个属性都有 value_per_locale 和 value_per_channel。二者共同决定一个属性在一个产品上对应多少行,以及读取时会返回哪一行:
value_per_channel | value_per_locale | 每个产品的行数 |
|---|---|---|
| false | false | 1 |
| false | true | 每种语言区域一行 |
| true | false | 每个渠道一行 |
| true | true | 每个渠道、每种语言区域一行 |
Product::getCustomAttributeValue() 会根据请求的渠道和语言区域解析正确的行;如果请求的渠道或语言区域没有值,则回退到默认渠道和语言区域。在第二种语言区域中“消失”的值,几乎总是因为写入属性时没有遵循这些标志。
数据表通过 (channel, locale, attribute_id, product_id) 上的唯一索引强制执行此规则,因此写入错误的作用域组合会导致约束冲突,而不是静默地产生重复记录。
不可妥协事项
- 遍历整个代码库。
AttributeRepository、AttributeFamilyRepository、AttributeGroupRepository、AttributeOptionRepository——绝不要手动写入product_attribute_values。 - 从属性中读取列名,通过
column_name或$attributeTypeFields。硬编码列名迟早会因遇到第一个非文本属性而出错。 - 每次写入都要遵循
value_per_locale和value_per_channel,而不仅仅是在读取时遵循。对于按语言区域限定的属性,如果只写入一行,就会丢失其他所有语言区域的值。 select/multiselect的值是选项 ID,而不是标签。select将一个 ID 存储在integer_value中;multiselect将逗号分隔的 ID 存储在text_value中。- 选项标签可翻译——它们存储在
attribute_option_translations中,因此,在一个语言区域添加的标签必须在全部 22 个语言区域中添加。 - 更改属性的
type会使其现有值失效,因为新类型会读取不同的列。应将其视为数据迁移,而不是编辑。 - 更改影响商品列表的内容后,必须重新索引。 可筛选属性和列表属性由扁平索引器反规范化到
product_flat中;在索引器运行前,网格和商城前台仍会显示旧值。
必需的子技能: 在宣布任何更改完成前,使用 bagisto-change-verification。