Magento2 Event Observer – Get Product Custom Attribute

custom-attributesevent-observermagento2

Anyone know how to get product custom attribute in observer? In my case event is controller_action_predispatch_checkout_cart_add.

My current code is giving me:

Uncaught Error: Call to a member function getProduct() on null in

 $product = $this->productRepository->getById($observer->getItem()->getProduct()->getId());
        $attr = $product->getData('product_customattribute');

Also I tried this (same error):

 $product = $observer->getEvent()->getProduct();
   $attr = $product->getProduct()->getAttributeText('product_customattribute');

UPDATE

My module redirect after click add to cart (with adding to the cart)

<?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="controller_action_predispatch_checkout_cart_add">
        <observer name="myvendor_mymodule_observer_redirect" instance="MyVendor\MyModule\Observer\Redirect" />
    </event>
</config>

and my Observer

<?php
namespace MyVendor\MyModule\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
//use Magento\Store\Model\StoreManager;
//use Magento\Framework\App\ObjectManager;

class Redirect implements  \Magento\Framework\Event\ObserverInterface
{
    /**
     * @var \Magento\Framework\App\ActionFlag
     */
    protected $actionFlag;

    /**
     * @var \Magento\Framework\App\Response\RedirectInterface
     */
    protected $redirect;
    protected $resultRedirect;

    public function __construct(
    //    \Magento\Framework\App\ActionFlag $actionFlag,
        \Magento\Framework\App\Response\RedirectInterface $redirect,
    //    StoreManager $storeManager,
        \Magento\Framework\Controller\ResultFactory $result,
        \Magento\Framework\App\ActionFlag $actionFlag
    )
    {
        $this->redirect = $redirect;
       // $this->actionFlag = $actionFlag;
        $this->resultRedirect = $result;
        $this->_actionFlag = $actionFlag;
      //  $this->storeManager = $storeManager;
    }
    public function execute(\Magento\Framework\Event\Observer $observer) {
        $controller = $observer->getControllerAction();
        $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
        $url = 'https://domain.com/url.html';
        $controller->getResponse()->setRedirect($url);
    }
}

I want change $url with custom attribute.
I was able to get product data using catalog_product_save_after but redirect wasn't working. Maybe I could connect somehow this two observers.

UPDATE 2

On this event I get custom attribute

checkout_cart_add_product_complete

 public function execute(\Magento\Framework\Event\Observer $observer) {
        $product = $observer->getProduct();
        $customAttribute = $product->getCustomAttribute('custom_attribute');
       $this->_logger->log(100,print_r( $customAttribute, true));
}

On this I get redirect after add to cart

controller_action_predispatch_checkout_cart_add

    public function execute(\Magento\Framework\Event\Observer $observer) {
            $controller = $observer->getControllerAction();
            $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
          $url = '/cart';  //should be custom_attribute

            $controller->getResponse()->setRedirect($url);
}

But I can get this values in one observer. I tried to connect them but not sure what should I use? Cache? register? to pass data from one observer to another.

Best Answer

If you are listening on checkout_cart_add_product_complete you have the following items on the $observer

 ['product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse()]

Your code should look smth like this

$product = $observer->getProduct(); // or $observer->getData('product');
$customAttribute = $product->getCustomAttribute('custom_attribute_code');
// to avoid errors double check that this product 
// has the custom attribute associated to it
$value = $customAttribute !== null ? $customAttribute->getValue() : null;

It's also a good practice to use the debugger to see what is what and what properties and values are available on a given object.

Hope this helps. Cheers.

EDIT as result of the comment

You do not have the product loaded at that point. You only have the controller instance and the request as it can be seen \Magento\Framework\App\Action\Action::dispatch(). You must have smth on the request like a product_id or product_sku.

In a development environment if you don't have xdebug(you should really take care of that, it pays off) the fastest way to debug stuff is var_dump($object->getData()).

On this specific event what you can do is inject the product repository in the constructor, get the product id from the request and load the product.

smth like

$product = $this->productRepository->getById($observer->getRequest()->getProductId())

Once you have the product above should apply. You can add some extra checks like, is there a request on the observer data? is there a product id on the request and so on.

Related Topic