问题描述
前台默认展示的是美国站的内容,正常情况下主站修改变体美国站会同步的,但目前有些链接的US站-简单变体-默认勾选会去掉-导致主站改变体时,US站未生效(前台默认是展示的US站)
这个默认勾选的问题导致现在如果链接变体需要修改没有关注到美国站(导致变体还是错的,对于产品组这边非常不方便)
同样美国站的图片配置偶尔也会出现与主站不同步的问题。
期望:需要修复该问题,应该主站修改变体,美国站会同步修改。
原理简述
Magento 2中存在配置层级系统,分别为Global(全局)、Website(网站)和Store(商店)。配置层级系统允许在不同层级上进行设置,这些设置会逐层继承。
-
Global(全局):
-
全局层级适用于所有网站和商店的通用配置。
-
例如:全局的货币设置,语言选项等。
-
-
Website(网站):(Fridayparts.com层级)
-
网站层级是用于管理多个商店的整体配置。
-
例如:支付方式,运输方式等,可以在同一网站下的多个商店中共享。
-
-
Store(商店):(美国商店所在层级)
-
商店层级是特定商店的配置。
-
例如:页面布局,显示设置等。
-
继承关系
-
默认继承关系:配置会从全局层级逐步继承到网站层级,再从网站层级继承到商店层级。
-
覆盖继承关系:在特定层级上可以覆盖上一级的配置。例如,您可以在商店层级覆盖网站层级的某些设置。
问题背景
-
当前状况:美国站是一个独立的网站(Website),它属于
Fridayparts.com
这个网站层级。 -
需求:在主站(
Fridayparts.com
)修改变体时,希望美国站(United States
)能同步变体,并且所有选项框默认勾选。
简单例子
假设您在配置中设置了“颜色”作为变体(也就是不同配置)选项,并希望默认选中“红色”:
-
全局层级:所有产品都可以有“颜色”选项,但没有默认颜色。
-
网站层级(
Fridayparts.com
):设置“红色”为默认选项。 -
商店层级(
United States
):默认继承“红色”选项(当没有设置自定义,也就是不存在复选框时)。如果设置了自定义,也就有了复选框的存在。那么,当你不将复选框打勾时,你可以单独在美国站设置成“蓝色”,当你打勾时就是继承上一层的“红色选项”。由于在开发过程中在这一部分设置了美国商店可以进行自定义,因此出现了该复选框,且该复选框是不打勾的,这样你可以选择是否自定义美国商店或继承上一层配置。
通俗解释
想象您有一个大公司(Global),公司下面有多个分公司(Websites),每个分公司下面有多个部门(Stores)。
-
您在公司总部(Global)发布了一个新的政策(配置)。
-
每个分公司(Website)都继承了这个政策。
-
每个部门(Store)如果没有特殊情况,也会遵守这个政策。
如果您需要一个分公司(Website)有特别的规定,可以在分公司层面设置。所有在这个分公司下的部门都会遵守这个新的规定,除非部门自己另有规定(覆盖配置)。
原因查找
考虑原因一:Biztech_Translator翻译插件导致的冲突
排查方式:通过新增产品,并配置Customizable Options ,在主站配置后:
其他站点默认继承该配置(勾选状态:Use Default Value),通过在主站配置后,在其他站点的配置也都会相应继承:(以下站点为美国站点配置显示)
通过对其他站点进行手动翻译,并没有对默认继承配置(也就是勾选状态:Use Default Value)造成影响。如数据库表所示(catalog_product_option表):
(catalog_product_option_title表)
因此,暂时排除其产生原因是由于Biztech_Translator翻译插件导致的冲突。
考虑原因二:运营那边在美国站首先新建了配置(舍弃)
当在美国站首先新建了配置时,主站会同步一个相同的配置,但是此时由于是先美国站创建的,属于自定义配置,因此会在数据库中产生两条分别的记录:
当对主站的配置进行修改时,不会影响到美国站的配置。如图所示:
但由于运营那边认为他们不可能先去配置美国站,因此该方向舍弃。
考虑处理:
- 只需要对Customizable Options中的美国站数据进行清洗。
- 美国站的图片信息进行清洗。
- 用store_id=0的数据去覆盖store_id!=0的数据
数据清洗
数据库表
-
catalog_product_entity_int: 存储整数类型的产品属性值。
这些表中的 store_id
列用于区分不同商店(如主站和美国站)的配置。当 "Use Default Value" 复选框勾选时,美国站会继承主站的配置,这意味着不会在 store_id = 1
的记录中存储具体的值,而是通过 store_id = 0
的值来进行继承。
数据库查询逻辑
要查找美国站(store_id = 1
)中没有勾选 "Use Default Value" 复选框的产品,可以检查这些表中是否存在 store_id = 1
的记录。
- catalog_product_option_type_title
- catalog_product_option_title
- catalog_product_entity_media_gallery_value
要将美国站 (store_id = 1
) 的产品配置数据清洗,使其使用主站 (store_id = 0
) 的数据,有以下几种方法:
数据清洗:删除美国站的数据
删除美国站特定属性的数据记录,使其自动继承主站的数据。在 Magento 中,如果某个商店(store)没有特定数据,它将继承默认商店(主站)的数据。
删除Customizable Options 部分配置的美国站记录。
对catalog_product_option_type_title表和catalog_product_option_title表进行数据清洗。
-- 删除 catalog_product_option_type_title 表中 store_id 为 1 的记录 DELETE FROM catalog_product_option_type_title WHERE store_id = 1; -- 删除 catalog_product_option_title 表中 store_id 为 1 的记录 DELETE FROM catalog_product_option_title WHERE store_id = 1;
删除Images And Videos 部分配置的美国站记录(图片)。
对catalog_product_entity_media_gallery_value表进行数据清洗。
查询数据SQL脚本:
WITH main_store_images AS ( SELECT mgv.entity_id, mg.value AS main_image, mg.disabled AS main_disabled FROM catalog_product_entity_media_gallery_value AS mgv JOIN catalog_product_entity_media_gallery AS mg ON mg.value_id = mgv.value_id WHERE mgv.store_id = 0 ), us_store_images AS ( SELECT mgv.entity_id, mg.value AS us_image, mg.disabled AS us_disabled FROM catalog_product_entity_media_gallery_value AS mgv JOIN catalog_product_entity_media_gallery AS mg ON mg.value_id = mgv.value_id WHERE mgv.store_id = 1 ) -- 查找主站与美国站图片路径和可见性配置不同的产品 SELECT us.entity_id AS product_id, us.us_image, main.main_image, us.us_disabled, main.main_disabled FROM us_store_images us LEFT JOIN main_store_images main ON us.entity_id = main.entity_id WHERE us.us_image != main.main_image OR us.us_disabled != main.main_disabled OR main.main_image IS NULL; -- 查找主站与美国站图片顺序配置不同的产品 SELECT us.entity_id AS product_id, us.value_id, us.us_position, main.main_position FROM us_store_image_positions us LEFT JOIN main_store_image_positions main ON us.entity_id = main.entity_id AND us.value_id = main.value_id WHERE us.us_position != main.main_position
删除sql脚本:
-- 删除 catalog_product_entity_media_gallery_value 表中 store_id 为 1 的记录 DELETE FROM catalog_product_entity_media_gallery_value WHERE store_id = 1;
站点数据覆盖
保存主站产品时用store_id=0的数据去覆盖store_id!=0的数据,并且需要对对应站点的内容进行翻译。例如对于catalog_product_option_title表,
option_id=6140时,有三个站点的数据,以title为例,如果是美国站由于跟主站使用相同的语言,可以直接赋值,如果是另外其他不使用英语的站点,考虑先拿到主站数据,进行翻译后,赋值给其他站点的内容。
Customizable Options title数据覆盖:
涉及表及字段:
catalog_product_option 属性:(product_id ,option_id)
catalog_product_option_title 属性:(option_title_id ,option_id ,store_id ,title )
catalog_product_option_type_value 属性:(option_type_id ,option_id )
catalog_product_option_type_title 属性(option_type_id ,store_id ,title)
图片位置信息覆盖:
涉及表及字段:
catalog_product_entity_media_gallery_value (value_id ,store_id ,entity_id ,position)
catalog_product_entity_media_gallery (value_id ,value)
相关类和方法:
#使用默认值的方法和代码 Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper.php :240
##Check product options and type options and save them Magento\Catalog\Model\Product.php :function beforeSave() $result = is_array($this->getData('options')) && count($this->getData('options')) > 0; 逻辑:当options存在且数量大于0的时候,表示其有自定义配置。
#产品信息保存方法 Magento\Catalog\Controller\Adminhtml\Product\Save.php :execute() #调用翻译方法 Biztech\Translator\Model\Translator :getTranslate()
实现代码部分展示:
private function updateOptionTitles($optionId) { // 获取 store_id 为 0 的 title $select = $this->connection->select() ->from(['cpot' => $this->resource->getTableName('catalog_product_option_title')], ['title']) ->where('option_id = ?', $optionId) ->where('store_id = ?', 0); $defaultTitle = $this->connection->fetchOne($select); if (!$defaultTitle) { return; } // 获取所有的 store_id!=0 的 title $select = $this->connection->select() ->from(['cpot' => $this->resource->getTableName('catalog_product_option_title')], ['store_id']) ->where('option_id = ?', $optionId) ->where('store_id != ?', 0); $storeTitles = $this->connection->fetchCol($select); $source = 'en'; foreach ($storeTitles as $titleStore) { // 判断是否是英语站点 if ($titleStore == 1) { // 复制 store_id 为 0 的值 $title = $defaultTitle; } else { // 翻译标题 $select = $this->connection->select() ->from(['store' => $this->resource->getTableName('store')], ['code']) ->where('store_id = ?', $titleStore); $target = $this->connection->fetchOne($select); $translate = $this->translator->getTranslate($defaultTitle, $target, $source); $title = $translate['text']; } // 更新 title $this->connection->update( $this->resource->getTableName('catalog_product_option_title'), ['title' => $title], ['option_id = ?' => $optionId, 'store_id = ?' => $titleStore] ); } }
测试结果
Customizable Options title数据库结果:(成功对其他外语站点的title进行了翻译覆盖)
图片位置信息测试结果:
未修正前图片位置数据:
修正后图片位置数据: