Shopware 6: Get seo product url in PHP

This code snippets shows you how to get the SEO url of a product by e.g. the id or productNumber.

The short version:

<?php

// $this->seoUrlReplacer = Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface

$host = $request->attributes->get(RequestTransformer::STOREFRONT_URL);
$parameter = ['productId' => $product->getId()];
$raw = $this->seoUrlReplacer->generate('frontend.detail.page', $parameter);

return $this->seoUrlReplacer->replace($raw, $host, $salesChannelContext);

The long version:

src/Resources/config/services.xml

<?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="Devert\UrlExample\Service\Product">
            <argument type="service" id="product.repository" />
            <argument type="service" id="Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface" />
        </service>
    </services>
</container>

src/Service/Product.php

<?php declare(strict_types=1);

namespace Devert\UrlExample\Service;

use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Storefront\Framework\Routing\RequestTransformer;
use Shopware\Core\Content\Seo\SeoUrlPlaceholderHandlerInterface;

class Product
{
    /**
     * @var EntityRepositoryInterface
     */
    private $productRepository;

    /**
     * @var SeoUrlPlaceholderHandlerInterface
     */
    private $seoUrlReplacer;

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

    /*
        Get Shopware Product Url by Product Number
    */
    public function getProductUrlByNumber($number, $salesChannelContext, $request)
    {
        $product = $this->findProductByNumber($number, $salesChannelContext);

        if(!$product)
        {
            return false;
        }

        $host = $request->attributes->get(RequestTransformer::STOREFRONT_URL);
        $parameter = ['productId' => $product->getId()];
        $raw = $this->seoUrlReplacer->generate('frontend.detail.page', $parameter);

        return $this->seoUrlReplacer->replace($raw, $host, $salesChannelContext);
    }

    /*
        Returns Shopware Product Entity by Product Number
    */
    public function findProductByNumber($number, $salesChannelContext)
    {
        $criteria = new Criteria();
        $criteria->setLimit(1);
        $criteria->addFilter(new EqualsFilter('productNumber', $number));

        $entities = $this->productRepository->search(
            $criteria,
            $salesChannelContext->getContext()
        )->getEntities();

        /** @var ProductEntity */
        foreach ($entities as $entity) {
            return $entity;
        }

        return false;
    }
}