Magneto2 How can I create dependent simple products?
First, parent simple product is added to cart & then the second simple product is added to cart.
If first is removed then display an error message.
How can I achieve this functionality?
So assuming a hard coded product parent-child relationship.
The product with sku="product-a" has a child sku="product-b"
I used observers for this, hooking into checkout_cart_product_add_after and sales_quote_remove_item.
app/code/StackExchange/DependentProduct/etc/events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<event name="checkout_cart_product_add_after">
<observer name="add_dependent_product_to_cart" instance="StackExchange\DependentProduct\Observer\AddDependentProductToCart" />
</event>
<event name="sales_quote_remove_item">
<observer name="remove_dependent_product_from_cart" instance="StackExchange\DependentProduct\Observer\RemoveDependentProductFromCart" />
</event>
</config>
app/code/StackExchange/DependentProduct/Observer/AddDependentProductToCart.php
<?php
declare(strict_types=1);
namespace StackExchange\DependentProduct\Observer;
use Magento\Catalog\Model\ProductRepository;
use Magento\Checkout\Model\Session;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Quote\Api\CartRepositoryInterface;
use Magento\Quote\Model\Quote;
class AddDependentProductToCart implements ObserverInterface
{
/**
* @var ProductRepository
*/
private ProductRepository $productRepository;
/**
* @var CartRepositoryInterface
*/
private CartRepositoryInterface $cartRepository;
/**
* @var Session
*/
private Session $checkoutSession;
public function __construct(
Session $checkoutSession,
ProductRepository $productRepository,
CartRepositoryInterface $cartRepository
) {
$this->productRepository = $productRepository;
$this->cartRepository = $cartRepository;
$this->checkoutSession = $checkoutSession;
}
public function execute(Observer $observer)
{
/** @var \Magento\Catalog\Model\Product $product */
$product = $observer->getEvent()->getData('product');
if ($product->getSku() != "product-a") {
return;
}
/** @var \Magento\Quote\Model\Quote\Item $quoteItem */
$quoteItem = $observer->getEvent()->getData('quote_item');
$productB = $this->productRepository->get('product-b');
$quote = $this->checkoutSession->getQuote();
$quote->addProduct($productB, (int) $quoteItem->getQty());
}
}
app/code/StackExchange/DependentProduct/Observer/RemoveDependentProductFromCart.php
<?php
declare(strict_types=1);
namespace StackExchange\DependentProduct\Observer;
use Magento\Catalog\Model\ProductRepository;
use Magento\Checkout\Model\Session;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Message\ManagerInterface as MessageManager;
use Magento\Quote\Api\CartRepositoryInterface;
class RemoveDependentProductFromCart implements ObserverInterface
{
private MessageManager $messageManager;
public function __construct(
MessageManager $messageManager
) {
$this->messageManager = $messageManager;
}
public function execute(Observer $observer)
{
/** @var \Magento\Quote\Model\Quote\Item $quoteItem */
$quoteItem = $observer->getEvent()->getData('quote_item');
if ($quoteItem->getSku() != "product-a") {
return;
}
$this->messageManager->addErrorMessage(__('Error message'));
}
}
You might need to review so that the correct qty are added to cart if a product is added several times. There is also another event checkout_cart_product_update_after you might want to look into. However, the above code shows the basic idea.
Good luck!