Product-Properties in Produkt-Slider

Hi @plusgrad,

meine service.xml sieht so aus:

<?xml version="1.0" ?>
<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="SupplierInfoListing\Subscriber\SupplierInfoListingManufacturerListing">
            <argument type="service" id="Shopware\Core\System\SystemConfig\SystemConfigService" />
            <argument type="service" id="service_container"/>
            <tag name="kernel.event_subscriber"/>
        </service>
        <service id="SupplierInfoListing\Subscriber\SupplierInfoListingManufacturerSearch">
            <argument type="service" id="Shopware\Core\System\SystemConfig\SystemConfigService" />
            <argument type="service" id="service_container"/>
            <tag name="kernel.event_subscriber"/>
        </service>
        <service id="SupplierInfoListing\Resolver\SupplierInfoListingProductSlider">
            <tag name="shopware.cms.data_resolver"/>
            <argument type="service" id="Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver"/>
        </service>
        <service id="SupplierInfoListing\Resolver\SupplierInfoListingProductBox">
            <tag name="shopware.cms.data_resolver"/>
            <argument type="service" id="Shopware\Core\Content\Product\Cms\ProductBoxCmsElementResolver"/>
        </service>
    </services>
</container>

Die service IDs und die classes SupplierInfoListingProductBox, SupplierInfoListingProductSlider, SupplierInfoListingManufacturerListing und SupplierInfoListingManufacturerSearch heißen bei dir wahrscheinlich anders, das musst du dann anpassen.

LG

Hallo!

@cinquecento stehe vor dem gleichen Problem. Hast du hier inzwischen eine Lösung gefunden?

Viele Grüße

Moin @SteVo,

leider bin ich mit dem CrossSellingCmsElementResolver bisher nicht weitergekommen.
Ich bin noch nicht so firm mit Shopware 6, dass ich das Problem alleine lösen kann.

Vielleicht kann @devnullroot ja helfen?

Liebe Grüße

Wieso gibt es hier kein Criteria-Event?

Hallo @cinquecento,

habe es nun über einen anderen Weg gelöst.

Hier der Eintrag aus der service.xml:

<service id="[dein-namespace]\CachedProductCrossSellingRouteExtended" 
                decorates="Shopware\Core\Content\Product\SalesChannel\CrossSelling\CachedProductCrossSellingRoute">
                <argument type="service" id="Shopware\Core\Content\Product\SalesChannel\CrossSelling\CachedProductCrossSellingRoute.inner"/>
                <argument type="service" id="cache.object"/>
                <argument type="service" id="Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator"/>
                <argument type="service" id="Shopware\Core\Framework\Adapter\Cache\CacheTracer"/>
                <argument type="service" id="event_dispatcher"/>
                <argument>%shopware.cache.invalidation.product_cross_selling_route%</argument>
                <argument type="service" id="logger"/>
        </service>
<?php declare(strict_types=1);

namespace [dein-namespace]\Service;

use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CachedProductCrossSellingRoute;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\HttpFoundation\Request;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Content\Product\SalesChannel\CrossSelling\ProductCrossSellingRouteResponse;

class CachedProductCrossSellingRouteExtended extends CachedProductCrossSellingRoute
{

	public function load(string $productId, Request $request, SalesChannelContext $context, Criteria $criteria) : ProductCrossSellingRouteResponse
	{

		$criteria->addAssociation('manufacturer');
        $criteria->addAssociation('properties.group');

		return parent::load($productId, $request, $context, $criteria);

	}

}

Vielleicht hilft es ja :slight_smile:

Viele Grüße!

4 Likes

ich habe auch Probleme, ich habe alles mögliche ausprobiert aber mein Subscriber befüllt die Daten nicht, ich möchte die Produkt-Slider in Erlebniswelten (mit dynamische Produktgruppen befüllt) erweitern. Der Slider greift ja auf die box-standard und wenn ich da ein dump auf die Produkte mache, dann bekommen ich bei Manufacturer z.B. null.

Meine Subscriber Events die ich bis jetzt ausprobiert habe:

            ProductEvents::PRODUCT_LOADED_EVENT => "onProductLoaded",
            ProductBoxCmsElementResolver::PRODUCT_LOADED_EVENT => "onProductBoxCmsLoaded",
            ProductSliderCmsElementResolver::PRODUCT_LOADED_EVENT => "onProductSliderCmsLoaded",
            ProductListingCriteriaEvent::PRODUCT_LOADED_EVENT => "onProductListingCriteriaEvent",
            ProductLoaderCriteriaEvent::class => 'productLoaderCriteria',
            'sales_channel.product.loaded' => 'onSalesChannelEntityLoadedEvent'

hey ich kann dir da leider nicht weiterhelfen. aber vielleicht hilft dir das hier, ich konnte mein Problem lösen:

Ich habe hiermit noch ein generelles Problem… wenn zwei Plugins ihre Associations hinzufügen wollen, überschreibt eines das andere, oder? Beispiel:

  1. Plugin holt sich eine Association auf manufacturer.media rein:
<?php declare(strict_types=1);

namespace foobar1\Core\Content\Product\Cms;

use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\DataResolver\CriteriaCollection;

class ManufacturerMediaProductSliderCmsElementResolver
{
    /** @var ProductSliderCmsElementResolver $elementResolver */
    private $elementResolver;

    public function __construct(ProductSliderCmsElementResolver $elementResolver)
    {
        $this->elementResolver = $elementResolver;
    }

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

    public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
    {
        $criteriaCollection = $this->elementResolver->collect($slot, $resolverContext);

        foreach ($criteriaCollection as $productCriteria) {
            foreach ($productCriteria as $criteria) {
                $criteria->addAssociation('manufacturer.media');
            }
        }

        return $criteriaCollection;
    }

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

Das 2. Plugin holt sich eine Association auf options.group rein.

<?php declare(strict_types=1);

namespace foobar2\Core\Content\Product\Cms;

use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\DataResolver\CriteriaCollection;

class OptionsProductSliderCmsElementResolver
{
    /** @var ProductSliderCmsElementResolver $elementResolver */
    private $elementResolver;

    public function __construct(ProductSliderCmsElementResolver $elementResolver)
    {
        $this->elementResolver = $elementResolver;
    }

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

    public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
    {
        $criteriaCollection = $this->elementResolver->collect($slot, $resolverContext);

        foreach ($criteriaCollection as $productCriteria) {
            foreach ($productCriteria as $criteria) {
                $criteria->addAssociation('options.group');
            }
        }

        return $criteriaCollection;
    }

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

Im Ergebnis ist dann die Association auf manufacturer.media des Plugin 1 futsch… Ist das so, oder mache ich hier einen Fehler?

addAssociation – wie das Englische Wort add ausdrückt – fügt eine weitere Association hinzu. Es überschreibt nichts.

Je nach Kontext erstellen die Plugins auch ihre eigene Criteria, dass diese dann voreinander getrennt sind.

Was bei dir schlief läuft, ist mir auf den ersten Blick nicht ersichtlich.

@Max_Shop so dachte ich das auch.

Nach meinen Tests liegt es auch nicht an addAssociation, sondern daran, dass bei Plugin 1 die collect-Function und die enrich-Funktion nicht mehr aufgerufen werden. getType() hingegen schon. Woran kann das liegen?

Es ist praktisch so, dass nur die collect-function des zuletzt installierten plugins aufgerufen wird.

Ich habe mir eben deinen Code angesehen…

Deine Class extended nicht die Abstract Class (nicht sicher, ob notwendig)

    foreach ($criteriaCollection as $productCriteria) {
            foreach ($productCriteria as $criteria) {
                $criteria->addAssociation('options.group');
            }
        }

Du erstellst eine $criteria Variable, verwirfst diese nach dem foreach aber wieder. Ich weiß nicht, was du dir da dann erhoffst.

Du musst die $criteria auch wieder der $criteriaCollection zuweisen.

@Max_Shop danke für die Rückmeldung.

Deine Class extended nicht die Abstract Class (nicht sicher, ob notwendig)

Hatte ich nicht gemacht, weil es in den obigen Code-Beispielen auch niemand gemacht hat… Ich habe mal extends auf extends ProductSliderCmsElementResolver eingefügt… machte aber keinen Unterschied

Du erstellst eine $criteria Variable, verwirfst diese nach dem foreach aber wieder. Ich weiß nicht, was du dir da dann erhoffst.

also quasi hiermit:
$criteriaCollection->add('product-slider' . '_' . $slot->getUniqueIdentifier(), ProductDefinition::class, $criteria);

Ich bin mir aber nicht sicher, ob das mein Problem löst… ich habe am Anfang der collect-Funktion ein dump('foobar1') eingefügt. Daher weiß ich, dass die Funktion gar nicht erst ausgeführt wird, wenn das zweite Plugin aktiv ist.

Ich brauche Kaffee… dump ist natürlich eine Symfony-Funktion (ursprüngliche Antwort war Unsinn).

extends AbstractCmsElementResolver wäre als extend vermutlich passender.

In deiner service.xml sind beide Class eingetragen?

@Max_Shop

nein dump läuft wunderbar und wird in der symfony console ausgegeben:

Wie gesagt, es funktioniert ja auch, wenn man nur eines der Plugins betrachtet… nur wenn zwei Plugins da dran wollen, wird die collect-Funktion des anderen nicht mehr ausgeführt…

1 Like

Aktualisiertes Codebeispiel:

PLUGIN 1:

<?php declare(strict_types=1);

namespace DockwareSamplePlugin\Core\Content\Product\Cms;

use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Cms\DataResolver\Element\AbstractCmsElementResolver;
use Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\DataResolver\CriteriaCollection;

class DockwareExtendProductSliderCmsElementResolver extends AbstractCmsElementResolver
{
    /** @var ProductSliderCmsElementResolver $elementResolver */
    private $elementResolver;

    public function __construct(ProductSliderCmsElementResolver $elementResolver)
    {
        $this->elementResolver = $elementResolver;
    }

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

    public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
    {
        $criteriaCollection = $this->elementResolver->collect($slot, $resolverContext);

        foreach ($criteriaCollection as $productCriteria) {
            foreach ($productCriteria as $criteria) {
                $criteria->addAssociation('media');
                dump('Dockware!');
                dump($productCriteria);
            }
        }

        return $criteriaCollection;
    }

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

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="DockwareSamplePlugin\Core\Content\Product\Cms\DockwareExtendProductSliderCmsElementResolver">
            <argument type="service" id="Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver"/>
            <tag name="shopware.cms.data_resolver"/>
        </service>
    </services>
</container>

PLUGIN 2:

<?php declare(strict_types=1);

namespace DockwareFooSamplePlugin\Core\Content\Product\Cms;

use Shopware\Core\Content\Cms\Aggregate\CmsSlot\CmsSlotEntity;
use Shopware\Core\Content\Cms\DataResolver\Element\AbstractCmsElementResolver;
use Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver;
use Shopware\Core\Content\Cms\DataResolver\Element\ElementDataCollection;
use Shopware\Core\Content\Cms\DataResolver\ResolverContext\ResolverContext;
use Shopware\Core\Content\Cms\DataResolver\CriteriaCollection;

class DockwareExtendProductSliderCmsElementResolver extends AbstractCmsElementResolver
{
    /** @var ProductSliderCmsElementResolver $elementResolver */
    private $elementResolver;

    public function __construct(ProductSliderCmsElementResolver $elementResolver)
    {
        $this->elementResolver = $elementResolver;
    }

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

    public function collect(CmsSlotEntity $slot, ResolverContext $resolverContext): ?CriteriaCollection
    {
        $criteriaCollection = $this->elementResolver->collect($slot, $resolverContext);

        foreach ($criteriaCollection as $productCriteria) {
            foreach ($productCriteria as $criteria) {
                $criteria->addAssociation('properties.group');
                dump('DockwareFoo!');
                dump($productCriteria);
            }
        }

        return $criteriaCollection;
    }

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

<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

    <services>
        <service id="DockwareFooSamplePlugin\Core\Content\Product\Cms\DockwareExtendProductSliderCmsElementResolver">
            <argument type="service" id="Shopware\Core\Content\Product\Cms\ProductSliderCmsElementResolver"/>
            <tag name="shopware.cms.data_resolver"/>
        </service>
    </services>
</container>

Das einzige, was mir momentan noch auffällt ist, dass bei fehlt. Ich bin mir aber nicht ganz sicher, ob dies in diesem Kontext notwendig ist. Dann duften diese vermutlich gar nicht ausgeführt werden.

Ich teste es später mal per Copy&Past.

@Max_Shop

Das einzige, was mir momentan noch auffällt ist, dass bei fehlt.

Dein Satz war leider nicht ganz vollständig. Falls Du beim Copy & Past einen Fehler findest sag gern bescheid. Ich kann Dir auch einen Dropbox-Link zu den beiden Demoplugins mit dem Code schicken.

@ myshoptheme dürfte ich dich um die beiden Plugins bitten? Sitze gerade vor dem gleichen Problem. Das wär super, danke dir! :slight_smile:
LG Alex

Hallo,

dieses Plugin löst das Problem:

sg Roman

Hej, wurde der Grund gefunden, warum der Resolver des zweiten Plugins nicht collect() und enrich() ausgeführt hatte? Sitze gerade vor dem gleichen Problem und erkenne einfach den Grund nicht.


Ok, habe nun den Grund gefunden:

Die Klasse CmsSlotsDataResolver fügt (Stand 4.12.0) im __construct() alle Einträge von $resolvers in ein assoziatives Array ein. Dabei wird der string von getType des Resolvers als key genutzt und mehrere Resolver eines CMS Elements überschreiben entsprechend den Vorherigen.

Somit ist es derzeit nicht möglich mehrere Resolver zu einem Element zu nutzen. :woozy_face: