Product-Properties in Produkt-Slider

Hi zusammen,

vielen Dank für eure vielen hilfreichen Hinweise! Leider hatte ich es damit trotzdem nicht geschafft, in Shopware 6.6 den Hersteller in die Produktslider zu bekommen. In meinem Fall laden die Slider die Produkte aus dynamischen Produktgruppen (AKA product streams). Nach einigem Debuggen habe ich dann herausgefunden, dass bei solchen Slidern in der ProductSliderCmsElementResolver::enrich() nicht einfach das Ergebnis mit den Kriterien aus ProductSliderCmsElementResolver::collect() zurückgegeben wird (dort wäre die komplette Herstellerentität nämlich schon drin), sondern auf Basis der Produkt-IDs nochmal eine separate Abfrage auf das Produkt-Repository gemacht wird (siehe ProductSliderCmsElementResolver::fetchProductsByIds()). Das Ergebnis dieser Abfrage kommt am Ende im Template an - leider ohne den Hersteller und ohne schicke Möglichkeit zum Einklinken.

Am Ende sieht meine Lösung so aus:

src/DataResolver/ProductSliderCmsElementResolver.php

<?php

declare(strict_types=1);

namespace Example\Plugin\DataResolver;

use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Cms\DataResolver\CriteriaCollection;
use Shopware\Core\Content\Cms\DataResolver\Element\AbstractCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\Element\CmsElementResolverInterface;
use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\SalesChannel\Struct\ProductSliderStruct;
use Shopware\Core\Content\Product\ProductEntity;

class ProductSliderCmsElementResolver extends AbstractCmsElementResolver
{
    protected const PRODUCT_SLIDER_ENTITY_FALLBACK = 'product-slider-entity-fallback';

    public function __construct(
        protected CmsElementResolverInterface $decorated,
    ) {
    }

    public function getType(): string
    {
        return $this->getDecorated()->getType();
    }

    public function getDecorated(): CmsElementResolverInterface
    {
        return $this->decorated;
    }

    public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
    {
        return $this->getDecorated()->collect($slot, $resolverContext);
    }

    public function enrich(CmsSlotEntity $slot, ResolverContext $resolverContext, ElementDataCollection $result): void
    {
        $this->getDecorated()->enrich($slot, $resolverContext, $result);

        $config = $slot->getFieldConfig();
        $productConfig = $config->get('products');

        if ($productConfig->isProductStream() && $productConfig->getValue()) {
            $entitySearchResult = $result->get(
                self::PRODUCT_SLIDER_ENTITY_FALLBACK . '_' . $slot->getUniqueIdentifier()
            );

            if ($entitySearchResult === null) {
                return;
            }

            /** @var ProductSliderStruct $slider */
            $slider = $slot->getData();
            $products = $slider->getProducts();

            /** @var \Shopware\Core\Content\Product\ProductEntity $product */
            foreach ($products as $product) {
                $productResult = $entitySearchResult->get($product->getId());

                if ($productResult instanceof ProductEntity) {
                    $product->setManufacturer($productResult->getManufacturer());
                }
            }
        }
    }
}

src/Resources/config/services.xml

<?xml version="1.0" ?>

<container xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns="http://symfony.com/schema/dic/services"
           xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"
>
    <services>
        <service id="Example\Plugin\DataResolver\ProductSliderCmsElementResolver"
                 decorates="Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver"
                 public="true"
        >
            <argument type="service" id="Example\Plugin\DataResolver\ProductSliderCmsElementResolver.inner"/>
            <tag name="shopware.cms.data_resolver"/>
        </service>
    </services>
</container>

src/Resources/views/storefront/component/product/card/box-standard.html.twig

{% sw_extends "@Storefront/storefront/component/product/card/box-standard.html.twig" %}

{% block component_product_box_name %}
    <a href="{{ seoUrl('frontend.detail.page', {productId: id}) }}"
       class="product-name"
       title="{{ name }}"
    >
        <span class="manufacturer">{{ product.manufacturer.translated.name }}</span>
        {{ name }}
    </a>
{% endblock %}

Die Herstellerentität aus dem ursprünglichen Ergebnis wird also einfach nur in das neue Ergebnis kopiert. Das ist natürlich fehleranfällig, theoretisch könnten Objekte im ursprünglichen Ergebnis fehlen und somit dann auch die Hersteller im neuen Ergebnis. Sauberer wäre es, in solche einem Fall nochmal eine Abfrage zu machen, um die fehlenden Herstellerdaten zu holen. Für meine Zwecke genügt der obige Workaround jedoch.