后台分类中的 Position 保存成功,只代表 catalog_category_product.position 已写入;前台是否使用它排序,还取决于分类的 Available Product Listing Sort By、Default Product Listing Sort By、主题参数以及搜索引擎查询。先不要反复拖动商品,取三个 SKU 做可核对的排序样本。

确认数据库中的 position 真正改变

SELECT c.entity_id AS category_id, p.sku, cp.position
FROM catalog_category_product cp
JOIN catalog_product_entity p ON p.entity_id = cp.product_id
JOIN catalog_category_entity c ON c.entity_id = cp.category_id
WHERE cp.category_id = 37
  AND p.sku IN ('SKU-A','SKU-B','SKU-C')
ORDER BY cp.position, p.entity_id;

若 position 没变,检查后台保存请求是否返回 200、管理员权限以及扩展是否覆盖分类保存。若数据已变,问题在前台排序链路。

看页面实际发送的排序参数

在分类页清除 URL 参数,观察地址栏和 Network 请求中是否出现 product_list_order。浏览器 Local Storage、Session 或主题脚本可能记住用户上次选择的 price/name 排序。使用无痕窗口访问同一 URL,能快速排除这一层。

后台分类的 Display Settings 中,把默认排序显式设置为 Position,并确认 Store View 左上角 Scope。若“Use Config Settings”勾选,真正值来自商店配置;不同 Store View 可能不同。

锚点分类和搜索引擎排序的区别

非锚点分类通常直接读取分类商品关系;锚点分类还会合并子分类商品,并可能通过搜索引擎构造集合。此时同一商品可能来自多条分类关系,position 不一定按你编辑的分类解释。可临时在预发布环境关闭锚点做对照,确认是否属于聚合结果。

检查主题或扩展是否强制 order

grep -R --line-number --include='*.php' --include='*.xml' \
  -E 'setOrder\(|addAttributeToSort|product_list_order|setDefaultOrder' \
  app/code app/design 2>/dev/null

常见扩展会按销量、库存或自定义属性重排,并在插件中忽略 position。找到代码后先在预发布禁用模块或布局块对照,不要直接改 vendor。

只清理需要的索引和缓存

php bin/magento indexer:status catalog_category_product catalog_product_category
php bin/magento indexer:reindex catalog_category_product catalog_product_category
php bin/magento cache:clean full_page block_html

如果使用 Varnish/CDN,再确认分类 URL 对象已失效。用 curl -s 抓取页面中三个 SKU 的出现顺序,比肉眼看图片稳定:

curl -s 'https://shop.example.com/category.html?sort_test=1' \
 | grep -n -E 'SKU-A|SKU-B|SKU-C'

验收时分别测试默认访问、显式 ?product_list_order=position、选择价格排序后再返回,以及另一个 Store View。只有默认访问使用后台位置、用户主动选择其他排序仍能生效,才是正确结果。