You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shopware 6列表页如何通过Twig获取子分类?

在Shopware 6列表页获取子分类的方法

Shopware 6默认不会在列表页的page.header.navigation.active中加载子分类数据,这是出于性能优化的考虑。你可以通过以下几种标准方式实现需求:

方法一:在Twig模板中直接调用分类仓库查询

你可以在Twig中通过repository服务直接查询指定分类的子项,记得加上缓存标签避免重复查询:

{% set categoryRepository = services.repository('category') %}
{% set criteria = services.criteria() %}
{# 过滤当前分类的子项,设置启用状态 #}
{% do criteria.addFilter(criteria.equals('parentId', page.header.navigation.active.id)) %}
{% do criteria.addFilter(criteria.equals('active', true)) %}
{% do criteria.addSorting(criteria.sort('position', 'ASC')) %}

{% set childCategories = categoryRepository.search(criteria, context) %}

{# 遍历子分类生成链接 #}
{% if childCategories %}
<div class="child-category-links">
    {% for category in childCategories %}
        <a href="{{ path('frontend.category.page', {'navigationId': category.id}) }}">{{ category.translated.name }}</a>
    {% endfor %}
</div>
{% endif %}

方法二:扩展列表页的PageLoader主动加载子分类

如果需要在多个模板中复用,更推荐通过扩展ProductListingPageLoader来在页面加载时就把子分类数据注入到页面变量中:

  1. 创建自定义插件,添加ProductListingPageLoader的装饰器:
<?php

namespace YourPlugin\Core\Content\Product\SalesChannel\Listing;

use Shopware\Core\Content\Category\CategoryEntity;
use Shopware\Core\Content\Category\CategoryRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Storefront\Page\Product\Listing\ProductListingPage;
use Shopware\Storefront\Page\Product\Listing\ProductListingPageLoaderInterface;
use Symfony\Component\HttpFoundation\Request;

class ExtendedProductListingPageLoader implements ProductListingPageLoaderInterface
{
    private ProductListingPageLoaderInterface $originalLoader;
    private CategoryRepositoryInterface $categoryRepository;

    public function __construct(ProductListingPageLoaderInterface $originalLoader, CategoryRepositoryInterface $categoryRepository)
    {
        $this->originalLoader = $originalLoader;
        $this->categoryRepository = $categoryRepository;
    }

    public function load(Request $request, SalesChannelContext $context): ProductListingPage
    {
        $page = $this->originalLoader->load($request, $context);
        $activeCategory = $page->getHeader()->getNavigation()->getActive();

        if ($activeCategory instanceof CategoryEntity) {
            $criteria = new Criteria();
            $criteria->addFilter(new EqualsFilter('parentId', $activeCategory->getId()));
            $criteria->addFilter(new EqualsFilter('active', true));
            $criteria->addSorting(new FieldSorting('position', FieldSorting::ASCENDING));

            $childCategories = $this->categoryRepository->search($criteria, $context->getContext());
            $page->addExtension('childCategories', $childCategories);
        }

        return $page;
    }
}
  1. 在插件的services.xml中注册装饰器:
<service id="YourPlugin\Core\Content\Product\SalesChannel\Listing\ExtendedProductListingPageLoader"
         decorates="Shopware\Storefront\Page\Product\Listing\ProductListingPageLoader">
    <argument type="service" id="YourPlugin\Core\Content\Product\SalesChannel\Listing\ExtendedProductListingPageLoader.inner"/>
    <argument type="service" id="category.repository"/>
</service>
  1. 之后在模板中直接调用扩展的数据:
{% set childCategories = page.extensions.childCategories %}
{% if childCategories %}
    {# 这里编写你的遍历渲染逻辑 #}
{% endif %}

方法三:自定义CMS元素的DataResolver

如果是在自定义CMS元素中使用,可以通过实现CmsElementResolverInterface来在CMS元素渲染时获取子分类数据:

<?php

namespace YourPlugin\Core\Content\Cms\Resolver;

use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Cms\DataResolver\ElementResolver\AbstractCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\ElementResolver\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\EntityResolverContext;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Category\CategoryRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;

class ChildCategoryLinkResolver extends AbstractCmsElementResolver
{
    private CategoryRepositoryInterface $categoryRepository;

    public function __construct(CategoryRepositoryInterface $categoryRepository)
    {
        $this->categoryRepository = $categoryRepository;
    }

    public function getType(): string
    {
        return 'child-category-links'; // 替换为你的CMS元素类型标识
    }

    public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?ElementDataCollection
    {
        if (!$resolverContext instanceof EntityResolverContext) {
            return null;
        }

        $entity = $resolverContext->getEntity();
        if ($entity->getEntityName() !== 'category') {
            return null;
        }

        $criteria = new Criteria();
        $criteria->addFilter(new EqualsFilter('parentId', $entity->getId()));
        $criteria->addFilter(new EqualsFilter('active', true));

        $childCategories = $this->categoryRepository->search($criteria, $resolverContext->getContext());

        $data = new ElementDataCollection();
        $data->set('childCategories', $childCategories);

        return $data;
    }
}

注册 resolver 后,在你的CMS元素模板中就可以直接使用element.data.childCategories来获取子分类数据。


内容的提问来源于stack exchange,提问作者CodeEditor712

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:05:28