Magento 2特定分类库存为0时自定义显示需求求助
解决方案:针对特定分类的缺货商品自定义展示逻辑
一、第三方扩展推荐
如果不想自行开发,可以选择Magento官方市场的成熟扩展,直接通过后台配置实现需求:
- Custom Stock Status for Magento 2:支持为指定分类/商品设置自定义库存状态文本,可控制加购按钮显示状态,后台配置界面直观,兼容back order模式。
- Advanced Inventory Manager:除基础库存管理功能外,支持按分类配置缺货商品的展示规则,包括是否强制显示商品、替换提示文本、隐藏加购按钮,配置项集成在后台库存管理模块中。
二、自定义代码实现方案(适合具备开发能力的场景)
以下是完整的自定义模块实现步骤,可实现后台可配置的分类级缺货逻辑:
1. 创建基础模块结构
创建命名为Vendor_CustomStock的模块,包含以下核心文件:
registration.php:模块注册文件etc/module.xml:模块配置文件etc/adminhtml/acl.xml:权限控制文件(配置后台访问权限)
2. 添加后台配置项
在etc/adminhtml/system.xml中添加可配置项,让管理员指定目标分类和自定义提示文本:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <section id="custom_stock" translate="label" type="text" sortOrder="100" showInDefault="1" showInWebsite="1" showInStore="1"> <label>自定义库存设置</label> <tab>catalog</tab> <resource>Vendor_CustomStock::config</resource> <group id="category_rules" translate="label" type="text" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>分类专属库存规则</label> <field id="target_categories" translate="label" type="multiselect" sortOrder="10" showInDefault="1" showInWebsite="1" showInStore="1"> <label>目标分类</label> <source_model>Magento\Catalog\Model\Category\Source\Tree</source_model> </field> <field id="out_of_stock_text" translate="label" type="text" sortOrder="20" showInDefault="1" showInWebsite="1" showInStore="1"> <label>缺货自定义提示文本</label> <comment>目标分类下商品缺货时显示的文本</comment> </field> </group> </section> </system> </config>
在etc/config.xml中设置默认配置值:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Store:etc/config.xsd"> <default> <custom_stock> <category_rules> <out_of_stock_text>该商品已无法购买</out_of_stock_text> </category_rules> </custom_stock> </default> </config>
3. 拦截产品可见性与加购按钮逻辑
通过插件修改核心逻辑,确保目标分类的缺货商品强制显示、隐藏加购按钮:
插件配置(etc/frontend/di.xml)
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <!-- 拦截产品可见性判断 --> <type name="Magento\Catalog\Model\Product"> <plugin name="customstock_product_visibility" type="Vendor\CustomStock\Plugin\ProductVisibilityPlugin" sortOrder="10"/> </type> <!-- 拦截加购按钮显示判断 --> <type name="Magento\Catalog\Block\Product\View\AddToCart"> <plugin name="customstock_hide_addtocart" type="Vendor\CustomStock\Plugin\HideAddToCartPlugin" sortOrder="10"/> </type> </config>
产品可见性插件(Vendor/CustomStock/Plugin/ProductVisibilityPlugin.php)
<?php namespace Vendor\CustomStock\Plugin; use Magento\Catalog\Model\Product; use Magento\Framework\App\Config\ScopeConfigInterface; class ProductVisibilityPlugin { protected $scopeConfig; public function __construct(ScopeConfigInterface $scopeConfig) { $this->scopeConfig = $scopeConfig; } public function afterIsVisibleInCatalog(Product $subject, $result) { if ($result) { return $result; } // 获取后台配置的目标分类ID $targetCatIds = $this->scopeConfig->getValue( 'custom_stock/category_rules/target_categories', \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); if (!$targetCatIds) { return $result; } $targetCatIds = explode(',', $targetCatIds); $productCatIds = $subject->getCategoryIds(); // 判断商品是否在目标分类中,且缺货+开启back order $isInTargetCat = !empty(array_intersect($targetCatIds, $productCatIds)); if ($isInTargetCat && !$subject->getIsInStock() && $subject->getBackorders() != 0) { return true; } return $result; } }
隐藏加购按钮插件(Vendor/CustomStock/Plugin/HideAddToCartPlugin.php)
<?php namespace Vendor\CustomStock\Plugin; use Magento\Catalog\Block\Product\View\AddToCart; use Magento\Framework\App\Config\ScopeConfigInterface; class HideAddToCartPlugin { protected $scopeConfig; public function __construct(ScopeConfigInterface $scopeConfig) { $this->scopeConfig = $scopeConfig; } public function afterIsPossibleBuyFromThis(AddToCart $subject, $result) { $product = $subject->getProduct(); $targetCatIds = $this->scopeConfig->getValue( 'custom_stock/category_rules/target_categories', \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); if (!$targetCatIds) { return $result; } $targetCatIds = explode(',', $targetCatIds); $productCatIds = $product->getCategoryIds(); $isInTargetCat = !empty(array_intersect($targetCatIds, $productCatIds)); if ($isInTargetCat && !$product->getIsInStock() && $product->getBackorders() != 0) { return false; } return $result; } }
4. 替换缺货提示文本
复制Magento默认库存模板vendor/magento/module-catalog/view/frontend/templates/product/view/stock.phtml到app/code/Vendor/CustomStock/view/frontend/templates/product/view/stock.phtml,修改为以下内容:
<?php /** @var \Magento\Catalog\Block\Product\View\Stock $block */ /** @var \Magento\Framework\Escaper $escaper */ $product = $block->getProduct(); $stockMessage = $block->getStockStatus(); // 获取自定义配置 $customText = $block->getScopeConfig()->getValue( 'custom_stock/category_rules/out_of_stock_text', \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); $targetCatIds = $block->getScopeConfig()->getValue( 'custom_stock/category_rules/target_categories', \Magento\Store\Model\ScopeInterface::SCOPE_STORE ); // 判断是否替换文本 $replaceText = false; if ($targetCatIds) { $targetCatIds = explode(',', $targetCatIds); $productCatIds = $product->getCategoryIds(); $replaceText = !empty(array_intersect($targetCatIds, $productCatIds)) && !$product->getIsInStock() && $product->getBackorders() != 0; } if ($replaceText) { $stockMessage = $customText ?: '该商品已无法购买'; } ?> <?php if ($block->displayProductStockStatus()): ?> <div class="stock available" title="<?= $escaper->escapeHtmlAttr(__('Availability')) ?>"> <span><?= $escaper->escapeHtml($stockMessage) ?></span> </div> <?php endif; ?>
在etc/frontend/layout/catalog_product_view.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> <referenceBlock name="product.info.stock"> <action method="setTemplate"> <argument name="template" xsi:type="string">Vendor_CustomStock::product/view/stock.phtml</argument> </action> </referenceBlock> </body> </page>
5. 模块安装与测试
执行以下命令完成模块部署:
bin/magento setup:upgrade bin/magento setup:di:compile bin/magento setup:static-content:deploy -f bin/magento cache:flush
之后在后台进入** Stores > Configuration > Catalog > 自定义库存设置**,选择目标分类“overstock sale”,配置自定义提示文本,保存后测试对应分类下的缺货商品即可。
内容的提问来源于stack exchange,提问作者Saif
相关产品推荐
相关产品推荐

