Magento2 - Comment empêcher un produit d'être ajouté au panier par programme?

13

Ce que je veux faire, c'est que si mon attribut personnalisé est défini dans le devis, je ne veux pas qu'un produit soit ajouté au panier. Mon attribut personnalisé est correctement défini.

Pour éviter que le produit ne soit ajouté au panier, j'ai écrit un observateur qui observe cet événement controller_action_predispatch_checkout_cart_add

Mon code de fichier d'observateur:

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');          
        }
    }       
}

Avec ce code, je ne peux pas arrêter le processus d'ajout au panier.

Donc, selon cette réponse de Magento1 - /programming/14190358/stop-add-to-cart-and-supply-message-to-user-in-magento . J'ai essayé de remplacer

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

avec (Ce n'est pas la meilleure façon de le faire. S'il y a une meilleure façon, veuillez suggérer)

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

Cela arrête finalement le processus d'ajout au panier, mais le bouton Ajouter au panier continue d'afficher "Ajout" . Comment puis-je effectuer cela correctement afin que le bouton Ajouter au panier revienne à son état précédent et que le produit ne soit pas ajouté au panier?

entrez la description de l'image ici

Reena Parekh
la source
salut @reena pouvez-vous m'aider comment vous avez fait cela
mcoder
@mcoder - je l'ai fait avec un plugin. vous pouvez vous référer à la réponse acceptée ci-dessous pour plus de détails.
Reena Parekh
J'ai essayé mais je ne peux pas. Pouvez-vous m'aider comment vous avez fait? J'ai le même problème que vous voyez ce que j'ai essayé: magento.stackexchange.com/questions/111231/… mais cela n'a pas fonctionné
mcoder
je veux rediriger vers une URL externe comme google.com j'ai essayé ci-dessous une redirection vers ajax ajouter une URL de panier, je suis coincé pendant deux jours mais je n'ai pas pu le faire :(. Je vais essayer de faire un don pour vous aider
mcoder
Comment pouvez-vous trouver une solution ?? pouvez-vous me donner tout le fichier avec du code? j'ai le même problème
Jigs Parmar

Réponses:

22

vous pouvez essayer de définir le paramètre du produit sur false, puis définir le paramètre 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.'));

Le contrôleur du panier vérifie si le paramètre du produit est défini ici: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L99

et si ce n'est pas le cas, il appelle goBack. la méthode goBack vérifie si vous avez fait une demande ajax (je pense que vous l'avez fait), puis retourne un param backUrl supplémentaire dans la réponse ajax.

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

La méthode getBackUrl renvoie ensuite le paramètre return_url:

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

=== MISE À JOUR ===

ok puisque l'ajout de message ne fonctionne pas ici, vous devriez essayer d'une autre manière (c'est aussi plus simple)

créez un plugin pour Intercetp avant cette fonction: https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Model/Cart.php#L341

Si vous ne voulez pas que votre produit soit ajouté, lancez simplement une exception avec le message souhaité. Vous trouverez un joli tutoriel pour créer des plugins ici: http://alanstorm.com/magento_2_object_manager_plugin_system

L'ajout de produit doit être interrompu et l'exception doit être restituée sous forme de message https://github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/Controller/Cart/Add.php#L137

ajoutez le type suivant à vos modules 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>

Ensuite, la classe Vendor/Module/Model/Checkout/Cart/Plugindevrait ressembler à ceci:

<?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
la source
1
Merci David. Votre solution fonctionne, vote positif de ma part. Cependant, le message d'erreur ne s'affiche pas. Je suppose à cause de cette ligne: github.com/magento/magento2/blob/2.0/app/code/Magento/Checkout/… ? Pouvez-vous suggérer comment résoudre ce problème?
Reena Parekh
1
oui, jut a ajouté une autre solution. Assurez-vous de nettoyer le dossier var / generation et le cache de configuration pour que ces modifications soient appliquées
David Verholen
Utilisé votre 1ère méthode mais pas en mesure d'obtenir le message d'erreur, comment puis-je définir l'URL de retour et le message dans votre 2ème méthode.
Amit Singh
1
Pouvez-vous dire comment obtenir des valeurs d'options personnalisées ici?
anujeet
+1 Absolument génial! Solution parfaite (la mise à jour). Fonctionne avec 2.1.5.
Dave
2

Ci-dessous mon code pour empêcher l'ajout de produit au panier et afficher un message d'erreur à l'aide de l'observateur.

<?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.'));
            }
        }
    }
}

vous pouvez définir les conditions selon vos besoins pour empêcher l'ajout de produit au panier.

Vips Lucky
la source
Cela a fonctionné pour moi.
Hassan Al-Jeshi
0

Supprimez le code des trois dernières lignes

Et ajoutez cette seule ligne: return false; Et définissez la valeur du produit param: false Ensuite, vous obtenez un message d'erreur et le chargeur est masqué ... Merci

Kamal Jain
la source