Magento2: ¿cómo evitar que un producto se agregue al carrito mediante programación?

13

Lo que quiero hacer es que si mi atributo personalizado se establece entre comillas, no quiero que se agregue ningún producto en el carrito. Mi atributo personalizado se está configurando correctamente.

Para evitar que el producto se agregue al carrito, he escrito un Observador que observa este evento controller_action_predispatch_checkout_cart_add

Mi código de archivo de observador:

public function execute(\Magento\Framework\Event\Observer $observer) {
    $addedItemId = $observer->getRequest()->getParam('product');
    $quote       = $this->_cart->getQuote();

    if(!empty($quote)) {
        $customAttribute = $quote->getData('custom_attribute');

        if(!empty($customAttribute)) {
             $controller = $observer->getControllerAction();
             $storeId     = $this->_objectManager->get('Magento\Store\Model\StoreManagerInterface')->getStore()->getId();
             $product    = $this->_productRepository->getById($addedItemId, false, $storeId);
             $observer->getRequest()->setParam('product', null);

             $this->_messageManager->addError(__('This product cannot be added to your cart.'));
             echo false;            

             $this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
             $this->redirect->redirect($controller->getResponse(), 'checkout/cart/index');          
        }
    }       
}

Con este código, no puedo detener el proceso de agregar al carrito.

Entonces, según esta respuesta de Magento1: /programming/14190358/stop-add-to-cart-and-supply-message-to-user-in-magento . Traté de reemplazar

$this->_actionFlag->set('', \Magento\Framework\App\Action\Action::FLAG_NO_DISPATCH, true);
$this->redirect->redirect($controller->getResponse(), 'checkout/cart/index');  

con (Esta no es la mejor manera de hacerlo. Si hay una mejor manera, sugiérale)

header("Location: " . $product->getProductUrl());
die();

Esto finalmente detiene el proceso de agregar al carrito, pero el botón Agregar al carrito sigue mostrando "Agregar" . ¿Cómo puedo realizar esto correctamente para que el botón Agregar al carrito vuelva a su estado anterior y el producto tampoco se agregue al carrito?

ingrese la descripción de la imagen aquí

Reena Parekh
fuente
hola @reena puedes ayudarme cómo hiciste eso
mcoder
@mcoder: lo hice con un complemento. Puede consultar la respuesta aceptada a continuación para obtener más detalles.
Reena Parekh
Lo intenté, pero no puedo. ¿Pueden ayudarme? ¿Cómo lo hizo? Tengo el mismo problema que usted ve lo que intenté: magento.stackexchange.com/questions/111231/… pero no funcionó
mcoder
quiero redirigir a una url externa como google.com probé debajo de una redirigir a ajax agregar url de carrito, estoy atascado durante dos días pero no pude hacerlo :(. Intentaré donar por tu ayuda
mcoder
¿Cómo puedes obtener una solución? ¿me puede dar todo el archivo con el código? tengo el mismo problema
Jigs Parmar

Respuestas:

22

podría intentar establecer el parámetro del producto en falso y luego establecer el parámetro return_url:

$observer->getRequest()->setParam('product', false);
$observer->getRequest()->setParam('return_url', $this->_redirect->getRefererUrl());
$this->_messageManager->addError(__('This product cannot be added to your cart.'));

El controlador del carrito verifica si el parámetro del producto está configurado aquí: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L99

y si no es así, llama a goBack. el método goBack comprueba si realizó una solicitud ajax (creo que lo hizo) y luego devuelve un parámetro adicional backUrl en la respuesta ajax.

https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L165

El método getBackUrl luego devuelve el parámetro return_url:

https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart.php#L113

=== ACTUALIZACIÓN ===

ok ya que el mensaje que agrega no funciona aquí, deberías intentarlo de otra manera (también es más sencillo)

cree un complemento para Intercetp antes de esta función: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Model/Cart.php#L341

Si no desea que se agregue su producto, simplemente inicie una Excepción con el Mensaje deseado. Aquí encontrará un buen tutorial para crear complementos: http://alanstorm.com/magento_2_object_manager_plugin_system

La adición del producto debe interrumpirse y la excepción debe mostrarse como mensaje https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L137

agregue el siguiente tipo a sus módulos, etc / frontend / di.xml

<type name="Magento\Checkout\Model\Cart">
    <plugin name="interceptAddingProductToCart"
            type="Vendor\Module\Model\Checkout\Cart\Plugin"
            sortOrder="10"
            disabled="false"/>
</type>

Entonces la clase Vendor/Module/Model/Checkout/Cart/Plugindebería verse así:

<?php
namespace Vendor\Module\Model\Checkout\Cart;

use Magento\Framework\Exception\LocalizedException;

class Plugin
{
    /**
     * @var \Magento\Quote\Model\Quote
     */
    protected $quote;

    /**
     * Plugin constructor.
     *
     * @param \Magento\Checkout\Model\Session $checkoutSession
     */
    public function __construct(
        \Magento\Checkout\Model\Session $checkoutSession
    ) {
        $this->quote = $checkoutSession->getQuote();
    }

    /**
     * beforeAddProduct
     *
     * @param      $subject
     * @param      $productInfo
     * @param null $requestInfo
     *
     * @return array
     * @throws LocalizedException
     */
    public function beforeAddProduct($subject, $productInfo, $requestInfo = null)
    {
        if ($this->quote->hasData('custom_attribute')) {
            throw new LocalizedException(__('Could not add Product to Cart'));
        }

        return [$productInfo, $requestInfo];
    }
}
David Verholen
fuente
1
Gracias David. Tu solución funciona, vota de mí. Sin embargo, el mensaje de error no se muestra. Supongo que debido a esta línea: github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/… ? ¿Pueden sugerirme cómo puedo resolver eso?
Reena Parekh
1
Sí, Jut agregó otra solución. Asegúrese de limpiar la carpeta var / generation y la caché de configuración para que se apliquen estos cambios
David Verholen
Usó su primer método pero no pudo obtener el mensaje de error. ¿Cómo puedo configurar la URL de retorno y el mensaje en su segundo método?
Amit Singh
1
¿Puedes decir, cómo puedo obtener valores de opciones personalizadas aquí?
anujeet
+1 ¡Absolutamente brillante! Solución perfecta (la actualización). Funciona con 2.1.5.
Dave
2

A continuación se muestra mi código para evitar que el producto se agregue al carrito y muestre un mensaje de error con el observador.

<?php
use Magento\Framework\Event\ObserverInterface;

class ProductAddCartBefore implements ObserverInterface
{

    protected $_request;
    protected $_checkoutSession;
    protected $_messageManager;

    public function __construct(
        \Magento\Framework\App\RequestInterface $request,  
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Checkout\Model\SessionFactory $checkoutSession
    )
    {
        $this->_request = $request;
        $this->_messageManager = $messageManager;
        $this->_checkoutSession = $checkoutSession;
    }

    public function execute(\Magento\Framework\Event\Observer $observer)
    {
        $productId = $observer->getRequest()->getParam('product');

        $quote = $this->_checkoutSession->create()->getQuote();

        $itemsCount = $quote->getItemsSummaryQty();

        if($itemsCount > 0 && $productId != 1949)
        {
            if($quote->hasProductId(1949)) 
            {   
                $observer->getRequest()->setParam('product', false);
                $observer->getRequest()->setParam('return_url', false);
                $this->_messageManager->addErrorMessage(__('To proceed please remove other items from the cart.'));
            }
        }
    }
}

Puede establecer las condiciones según sus requisitos para evitar que el producto se agregue al carrito.

Vips Lucky
fuente
Esto funcionó para mí.
Hassan Al-Jeshi
0

Eliminar el último código de tres líneas

Y agregue esta línea: devuelva falso; Y establezca el valor del parámetro del producto: falso Entonces obtiene un mensaje de error y el cargador está oculto ... Gracias

Kamal Jain
fuente