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来在页面加载时就把子分类数据注入到页面变量中:
- 创建自定义插件,添加
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; } }
- 在插件的
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>
- 之后在模板中直接调用扩展的数据:
{% 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
相关产品推荐
相关产品推荐

