Back to Top

Custom Storefront Controller in Shopware6

Updated 23 November 2022

Introduction

This article give you a brief introduction on how to create a custom storefront controller in shopware6. If you want to create you own plugin then you need to know how to create a custom controller in storefront.

Overview

If you want to perform some custom business logic from your storefront , you will need to create a storefront controller . This article about to create a new product with help of custom controller.

Controller Class

For create a custom storefront controller in shopware6 . Create a class inside the <plugin base>/src/Storefront/Controller and name it ProductController.

<?php declare(strict_types=1);
use Shopware\Storefront\Controller\StorefrontController;
use Symfony\Component\Routing\Annotation\Route;
use Shopware\Core\Framework\Routing\Annotation\RouteScope;
use Shopware\Core\System\SalesChannel\SalesChannelContext;

/**
 * @RouteScope(scopes={"storefront"})
 */
class ProductController
{
    
     /**
     * @Route(
     *      "/storefront/products/",
     *      name="storefront.products",
     *      defaults={"productId": null, "csrf_protected"=false, "XmlHttpRequest"=true},
     *      methods={"GET", "POST", "DELETE"}
     * )
    */
     public function createShopwareProduct($productDetails, SalesChannelContext 
         $salesChannelContext)
    {
        $context = Context::createDefaultContext();
        $productRepository = $this->container->get('product.repository');
        
        // create product
        $id = !isset($productDetails['productId']) ? Uuid::randomHex() : $productDetails['productId'];
        $taxRepository = $this->container->get('tax.repository');
        $tax = $taxRepository->search((new Criteria())->addFilter(new EqualsFilter('id', $productDetails['tax'])), $context)->first();
        $grossPrice = $productDetails['price']+($productDetails['price']*$tax->getTaxRate())/100;

        $data = [
            'id' => $id,
            'productNumber' => $productDetails['number'],
            'description' => $productDetails['description'],
            'stock' => (int) $productDetails['stock'],
            'name' => $productDetails['name'],
            'price' => [
                [
                    'linked' => false,
                    'net' => (float) $productDetails['price'],
                    'gross' => (float) $grossPrice,
                    'currencyId' => Defaults::CURRENCY,
                ]
            ],
            'manufacturer' => ['id' => $productDetails['manufacturer']],
            'tax' => [
                'id' => $productDetails['tax']
            ],
        ];

        $categoryCollection = [];

        if (isset($productDetails['category']) && $productDetails['category']) {
            $productDetails['category'] = explode('&', $productDetails['category']);
            foreach ($productDetails['category'] as $category) {
                array_push($categoryCollection, ["id" => $category]);
            }

            $data['categories'] = $categoryCollection;
        }

        if (!isset($productDetails['productId'])) {
            $data['visibilities'] = [
                ['salesChannelId' => $salesChannelContext->getSalesChannel()->getId(), 'visibility' => ProductVisibilityDefinition::VISIBILITY_ALL],
            ];
        }

        if (isset($productDetails['cover'])) {
            $data['cover'] = [
                'id' => Uuid::randomHex(),
                'position' => 1,
                'media' => [
                    'id' => $productDetails['cover']['id'],
                    'title' => $productDetails['cover']['title'],
                ],
            ];
        }

        if (isset($productDetails['media'])) {
            $data['media'] = [];
            foreach ($productDetails['media'] as $mediaDetails) {
                $media = [
                    'id' => Uuid::randomHex(),
                    'media' => [
                        'id' => $mediaDetails['id'],
                        'title' => $mediaDetails['title'],
                    ],
                ];

                array_push($data['media'], $media);
            }
        }

        if (isset($productDetails['active'])) {
            $data['active'] = $productDetails['active'];
        }

        try {
           
            $productRepository->upsert([$data], $context);

             // get last created product with the help of id
            $criteria = (new Criteria([$id]))
                ->addAssociation('cover');

            $createdProductCollection = $productRepository->search($criteria, $context);
            $createdProduct = $createdProductCollection->first();

            $response = [
                'status' => true,
                'createdProduct' => $createdProduct,
            ];
        } catch (\Exception $exception) {
            $response = [
                'status' => false,
                'exceptionCode' => $exception->getErrorCode(),
                'exceptionMessage' => $exception->getMessage(),
            ];
        }

        return $response;
    }

}

Register controller in route

Next you have to tell Symfony that it should search for routes in your /Controller folder. Therefore add an routes.xml inside the <plugin base>/src/Resources/config folder.

<?xml version="1.0" encoding="UTF-8" ?>
<routes xmlns="http://symfony.com/schema/routing"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://symfony.com/schema/routing
        https://symfony.com/schema/routing/routing-1.0.xsd">

    <import resource="../../**/Storefront/Controller/*ProductController.php" type="annotation" />
</routes>

Register Controller in service

Now you need to register your controller in the DI-Container, therefore edit the Resources/config/services.xml to look like this:

Start your headless eCommerce
now.
Find out More
<?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="Swag\StorefrontController\Storefront\Controller\ProductController" public="true">
            <argument type="service" id="Shopware\Core\Checkout\Cart\SalesChannel\CartService"/>

            <call method="setContainer">
                <argument type="service" id="service_container"/>
            </call>
        </service>
    </services>
</container>

Rendering Template

Lastly your Controller Action needs to return a Response object. You can render an own template via $this->renderStorefront() or forward to another action.

public function createShopwareProduct($productDetails, SalesChannelContext 
         $salesChannelContext)
{
     return $this->renderStorefront('add-product.html.twig', $response);
}

Triggering your controller

Now you need to trigger your custom action somehow. Add a anchor element that has an href to your route:

<a class="btn btn-primary btn-block" href={{ path('storefront/products') }}>
         Add Product
 </a>

To learn about more about this topic, there is a link.

I hope It will help you. Thanks for reading 🙂

. . .

Leave a Comment

Your email address will not be published. Required fields are marked*


Be the first to comment.

Back to Top

Message Sent!

If you have more details or questions, you can reply to the received confirmation email.

Back to Home