Webkul
Services
Technologies Bagisto QloApps
iOS Android SAP BigCommerce Wix
Trusted by
Samsung Intel Toyota Walmart Disney Nokia Nestlé Decathlon
See all customers
Back to Top
DEV

Custom Storefront Controller in Shopware6

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:

<?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