Search code examples
phpshopware

Load all variants of a product in Shopware (PHP)


I am trying to load all variations of a product.

While using google I found this code snippet:

class ProductViewSubscriber implements EventSubscriberInterface
{
    private EntityRepositoryInterface $productRepository;

    public function __construct(EntityRepositoryInterface $productRepository)
    {
        $this->productRepository = $productRepository;
    }

    public function getVariantsOfProduct(SalesChannelProductEntity $product, Context $context): EntitySearchResult
    {
        $parentProduct = $product->getParent();
        if ($parentProduct != null) {
            // We need the parent product to find all variants
            $product = $parentProduct;
        }

        $criteria = new Criteria();
        $criteria->addFilter(new EqualsFilter('product.parentId',
            $product->getUniqueIdentifier()));

        return $this->productRepository->search($criteria, $context);
    }

    public static function getSubscribedEvents(): array
    {
        return [
            ProductPageLoadedEvent::class => ['addVariants'],
        ];
    }

    public function addVariants(ProductPageLoadedEvent $pEvent)
    {
        $products = $this->getVariantsOfProduct($product = $pEvent->getPage()->getProduct(), $pEvent->getContext());
        $matchingVariants = $products->getElements();
    }
}

But using the code snippet only an empty list is returned, though there are definitely variants to that product. How can I fix this code?


Solution

  • It should work like this.

    <?php
    
    namespace TestPlugin\Subscriber;
    
    use Shopware\Core\Framework\Context;
    use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
    use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
    use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
    use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
    use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    
    class ProductPageLoadedSubscriber implements EventSubscriberInterface
    {
        private EntityRepositoryInterface $productRepository;
    
        public function __construct(EntityRepositoryInterface $productRepository)
        {
            $this->productRepository = $productRepository;
        }
    
        public static function getSubscribedEvents(): array
        {
            return [
                ProductPageLoadedEvent::class => 'addVariants'
            ];
        }
    
        public function addVariants(ProductPageLoadedEvent $pEvent)
        {
            $product = $pEvent->getPage()->getProduct();
    
            if (empty($productParentId = $product->getParentId())) { // Main product or has no variants
                return;
            }
    
            $products = $this->getVariantsOfProduct($productParentId, $pEvent->getContext());
            $matchingVariants = $products->getElements();
    
            var_dump($matchingVariants);
        }
    
        public function getVariantsOfProduct(string $productParentId, Context $context): EntitySearchResult
        {
            $criteria = new Criteria();
            $criteria->addFilter(new EqualsFilter('parentId', $productParentId));
    
            return $this->productRepository->search($criteria, $context);
        }
    }
    

    As far as I know, Shopware always loads a variant, so it is important that you check the ParentId, this provides the main product id, you can use this id to find out all the variants.