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 🙂
Be the first to comment.