5

I just have the simple requirement. I just need to add the product to a customer cart programatically in magento 2.

If i had to do it in magento 1.x, I would:

  1. Load the product with particular id or sku
  2. Load the customer from customer model using customer id.
  3. Load the checkout session for the customer and add the product to the cart model.(Not sure how exactly it would work but it would be something like that).

But I'm not sure how to achieve this on Magento 2.

If someone could suggest the flow and add the code snippet that that would be very helpful.

Any help would be well appreciated.

Thanks,

aton

  • Did you solve this problem? I have the same one. – Hoang Trinh Jun 12 '17 at 4:41
  • Hi piavgh, I have posted my answer, please have a look into it and try it. – aton1004 Jun 15 '17 at 5:00
  • Hi @aton1004, thank you for your answer. I figured it out and posted it here magento.stackexchange.com/questions/178633/…. Just have some problem related to mini cart doesn't refreshed. This solution does not require us to query database directly. – Hoang Trinh Jun 15 '17 at 7:19
6

Where you add products depends if you are using a controller or not.

But all you need is the Product Model and the Qty

With product module i mean a loaded Magento\Catalog\Model\Product. You can use Magento\Catalog\Api\ProductRepositoryInterface to get it with the sku or id of the product.

Do not use Magento\Checkout\Model\Cart as it is deprecated

Once you have done that use use Magento\Quote\Model\Quote::addProduct()

For example

...
use Magento\Quote\Model\QuoteFactory;
use Magento\Quote\Api\CartRepositoryInterface;
...
public function __construct(
...
QuoteFactory $quote,
CartRepositoryInterface $cartRep
...
){
...
$this->quote = $quote;
$this->cartRep = $cartRap;
...
}
...
function ... (){
...
try {
// if you need to get the quote by customerid
$quote = $this->cartRep->getActiveForCustomer($customerid);
// then load it
$cart = $this->quote->create()->loadActive($quote->getId());
$cart->addProduct($product, $qty);
} catch (\Exception $e) {
$this->messageManager->addErrorMessage($e->getMessage());
}
...
}

This code is not tested but it should work

| improve this answer | |
  • thanks for your answer. But i don't think you get my question completely. The quote needs to be of other customer not own. For example coach assigning product to his/her trainee. Did you get my requirement. Can above solve this? – aton1004 Jul 9 '18 at 5:50
  • Well what information do you have. Do you have a Quote ID to which he is adding products? Or how would you say it would work – CompactCode Jul 9 '18 at 9:14
  • A customer can have different quotes btw but sure if you have the customer id – CompactCode Jul 9 '18 at 9:14
  • Magento\Quote\Api\CartRepositoryInterface has a function that is called getActiveForCustomer($customerId, array $sharedStoreIds = []) with the description : Get active quote by id. – CompactCode Jul 9 '18 at 9:16
  • I edited the question. This is not tested and just a quick answer but it should work. You can also load in the customer model that you want to use and do $this->quote->loadByCustomer($customer). It depends on your preferences – CompactCode Jul 9 '18 at 9:24
5

You can use like this:-

<?php
namespace MyModule\AddToCart\Observer;

use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;

class AddToCart implements ObserverInterface
{
    protected $_productRepository;
    protected $_cart;
    protected $formKey;

    public function __construct(\Magento\Catalog\Model\ProductRepository $productRepository, \Magento\Checkout\Model\Cart $cart, \Magento\Framework\Data\Form\FormKey $formKey){
        $this->_productRepository = $productRepository;
        $this->_cart = $cart;
        $this->formKey = $formKey;
    }
    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $item = $observer->getEvent()->getData('quote_item');
        $product = $observer->getEvent()->getData('product');
        $item = ($item->getParentItem() ? $item->getParentItem() : $item);

        // Enter the id of the prouduct which are required to be added to avoid recurrssion
        if($product->getId() != 5){
            $params = array(
                'product' => 5,
                'qty' => $product->getQty()
            );
            $_product = $this->_productRepository->getById(5);
            $this->_cart->addProduct($_product,$params);
            $this->_cart->save();
        }

    }
}

I hope it's work.. And you can take more details Here

You can take also Here for more details.

| improve this answer | |
  • 1
    Hi payal thanks for your answer.I appreciate a lot but i didn't see where you have assigned the product to the customer. The links you have provided still lacks the solution to my requirement.I want to assign the product to another customer, do you have any other solution in mind? I will be happy to try that. – aton1004 Sep 23 '16 at 4:30
  • How can i assign this product to a specific customer cart? any solution? – srg Aug 24 '17 at 10:24
  • take my upvote. this is the right way how to add a product to the cart. People can adjust it however they want and i suggest always looking for a form_key – CompactCode Jul 2 '18 at 5:46
0

This is how I solved my above problem. I hope this will help others too. Below is the code of my controller file.

I think the code is self explanatory also please refer to the comments added on the code. Hope this will provide a walkaround.

<?php 


namespace Custom\Subscription\Controller\Index;


class Assign extends \Magento\Framework\App\Action\Action {

    protected $resultPageFactory;

    protected $quote;
    protected $messageManager;

    public function __construct(
        \Magento\Framework\App\Action\Context $context,
        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
        \Magento\Checkout\Model\Cart $quote,
        \Magento\Customer\Model\CustomerFactory $customerFactory,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository
    ){
        $this->resultPageFactory = $resultPageFactory;
        $this->getQuote = $quote;
        $this->customerFactory = $customerFactory;
        $this->messageManager = $messageManager;
        $this->customerRepository = $customerRepository;
        parent::__construct($context);
    }


    public function execute(){
        //die('I am working on this.');
        $customerSession = $this->_objectManager->get('Magento\Customer\Model\Session');
        if(!$customerSession->isLoggedIn()) {

            $this->_redirect('customer/account/');
        }
        $data = $this->getRequest()->getParams('id');
        $customerId = $data['id'];
        $quotes = $this->getQuote->getQuote();
         $quoteId = $quotes->getEntityId();     

        // var_dump($quote->getQuoteId());die();
        $_objectManager = \Magento\Framework\App\ObjectManager::getInstance();

        try{
        //try direct sql

        //take quote id of customer to assign here
        //get the quote id from quote table. there may be multiple quote of customer so take the last one
        $collecion = $_objectManager->create('Magento\Quote\Model\ResourceModel\Quote\Collection')->addFieldToFilter('customer_id',$customerId);
        $lastitem = $collecion->getLastItem();  
        //check if current customer has product in his cart.
        $itemCollection = $_objectManager->create('Magento\Quote\Model\ResourceModel\Quote\Item\Collection')->addFieldToFilter('quote_id',$quoteId);
        if(!count($itemCollection->getData())){
            $this->messageManager->addError( __('There are no products on the cart.Please add products to cart before assigning to customer.') );
        $this->_redirect('subscription/index/');        
        }else{
        //this will return the last Quote id of that customer
        $customerquoteId = $lastitem->getEntityId();
        $resource = $_objectManager->get('Magento\Framework\App\ResourceConnection');
        $connection = $resource->getConnection();
        $tableName = $resource->getTableName('quote_item'); //gives table name with prefix 
        //Update Data into table
        $sql = "Update " . $tableName . " Set quote_id = ".$customerquoteId." where quote_id =".$quoteId ;
        //var_dump($sql);die();
        $connection->query($sql);
        $this->messageManager->addSuccess( __('You have successfully assigned the product.') );
        //logout the coach 
        // $customerSession->logout();
        $this->_redirect('subscription/index/');
    }
        //ends here
    }catch (\Exception $e) {
                $message = $this->messageManager->addError(
                    __($e->getMessage())
                );
               $this->_redirect('subscription/index/');

            }



    }
}

There are few tables that should concern you: quote, quote_item. Please go through the table to understand how magento saves the item in cart.

I am using the direct SQL queries because magento don't let me update quote_item through model. Not sure if it the best way of achieving it.

Hope this will help!!

| improve this answer | |
  • 3
    Never ever use direct sqls :O And certainly not in a controller without any sanitzers. Talking about SQL injections :O:O – CompactCode Jul 2 '18 at 1:02
  • @SwAt.Be I can understand your concern, but I haven't taken any parameters or input from customer end, so will there be still possibility of SQL injection? Could you please suggest the approach how it can someone do sql injection above? – aton1004 Jul 2 '18 at 4:49
  • first of all products are added by using Magento\Checkout\Model\Cart -->addProduct() function. There is a lot of checks that need to pass in order to add a product to a cart. You skipped them all. Secondly you can easily send a POST with for instance Postman to the UpdatePost controller or whatever controller you are using giving it certain parameters. On Stackexchange we try to teach people how to do it in a good way ;) – CompactCode Jul 2 '18 at 5:44
  • Yes you are absolutely correct!! I didn't have proper approach at that time. Above answer from payal don't answer my question. Could you please add your answer with proper way of doing that, I can accept that answer so that it would be helpful for others. Thanks man!! – aton1004 Jul 2 '18 at 6:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.