I am trying to lookup the seoUrl of variants displayed on a product detail page - in the configurator.html.twig file. I have the option Id and have tried passing it as productId for the seoUrl function - but it doesn't return the correct seoUrl.
Searching for a solution, I found this question: Show all variations on the product detail page in Shopware 6 - which also lacks an answer. But it hinted that you should add the data using a Subscriber - is that really necessary?
You may decorate the ProductDetailRoute
, fetch the parent and with its children association and iterate them in the storefront template.
<service id="MyPlugin\Core\Content\Product\SalesChannel\Detail\ProductDetailRouteDecorator" public="true" decorates="Shopware\Core\Content\Product\SalesChannel\Detail\ProductDetailRoute">
<argument type="service" id="MyPlugin\Core\Content\Product\SalesChannel\Detail\ProductDetailRouteDecorator.inner"/>
<argument type="service" id="sales_channel.product.repository"/>
</service>
class ProductDetailRouteDecorator extends AbstractProductDetailRoute
{
private SalesChannelRepositoryInterface $productRepository;
private AbstractProductDetailRoute $decorated;
public function __construct(
AbstractProductDetailRoute $decorated,
SalesChannelRepositoryInterface $productRepository
) {
$this->decorated = $decorated;
$this->productRepository = $productRepository;
}
public function getDecorated(): AbstractProductDetailRoute
{
return $this->decorated;
}
public function load(string $productId, Request $request, SalesChannelContext $context, Criteria $criteria): ProductDetailRouteResponse
{
$response = $this->getDecorated()->load($productId, $request, $context, $criteria);
$product = $response->getProduct();
if (!$product->getParentId()) {
return $response;
}
$criteria = new Criteria([$product->getParentId()]);
$criteria->addAssociation('children');
$parent = $this->productRepository->search($criteria, $context)->first();
$product->setParent($parent);
return new ProductDetailRouteResponse($product, $response->getConfigurator());
}
}
{% if page.product.parent.children is defined %}
{% for child in page.product.parent.children %}
{{ seoUrl('frontend.detail.page', { productId: child.id }) }}
{% endfor %}
<br>
{% endif %}
Sample output:
http://localhost/Intelligent-Marble-Ultra-Beef/0491895660e94e32938022263595f861
http://localhost/Intelligent-Marble-Ultra-Beef/7c9f91d9051e40e0ba13d0e885e98d83
http://localhost/Intelligent-Marble-Ultra-Beef/f25c641abee446df82e1227cf200186c
A little more complex but with a lesser performance impact:
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('parentId', $product->getParentId()));
$ids = $this->productRepository->searchIds($criteria, $context)->getIds();
$product->addExtension('childrenIds', new ArrayStruct($ids));
{% if page.product.extensions.childrenIds is defined %}
{% for childId in page.product.extensions.childrenIds.all() %}
{{ seoUrl('frontend.detail.page', { productId: childId }) }}
<br>
{% endfor %}
{% endif %}