Magento 2: Проверка правил условий на основе атрибута продукта


Как проверить правила условий на основе атрибута продукта в magento 2

Серверная часть:

enter image description here

Код:

    $product_id = '3';  // Crown Summit Backpack sku is 24-MB03
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
    $rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();
    foreach ($rules as $rule) {
        $product = $objectManager->get('Magento\Catalog\Model\Product')->load($product_id);
        $item = $objectManager->create('Magento\Catalog\Model\Product');
        $item->setProduct($product);
        $validate = $rule->getActions()->validate($item);
    }
    var_dump($validate);
    var_dump($product);

Ожидаемый результат ложный, но он всегда показывает истинный. проверка атрибутов продукта выполнена неправильно.

var_dump($validate);

enter image description here

var_dump($product);

enter image description here

Vendor\Module\Model\Rule.php

<?php
namespace Vendor\Module\Model;
use Magento\Quote\Model\Quote\Address;
use Magento\Rule\Model\AbstractModel;
/**
 * Class Rule
 * @package Vendor\Module\Model
 *
 * @method int|null getRuleId()
 * @method Rule setRuleId(int $id)
 */
class Rule extends AbstractModel
{
    /**
     * Prefix of model events names
     *
     * @var string
     */
    protected $_eventPrefix = 'vendor_module';
    /**
     * Parameter name in event
     *
     * In observe method you can use $observer->getEvent()->getRule() in this case
     *
     * @var string
     */
    protected $_eventObject = 'rule';
    /** @var \Magento\SalesRule\Model\Rule\Condition\CombineFactory */
    protected $condCombineFactory;
    /** @var \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory */
    protected $condProdCombineF;
    /**
     * Store already validated addresses and validation results
     *
     * @var array
     */
    protected $validatedAddresses = [];
    /**
     * @param \Magento\Framework\Model\Context $context
     * @param \Magento\Framework\Registry $registry
     * @param \Magento\Framework\Data\FormFactory $formFactory
     * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
     * @param \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory
     * @param \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF
     * @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
     * @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
     * @param array $data
     * @SuppressWarnings(PHPMD.ExcessiveParameterList)
     */
    public function __construct(
        \Magento\Framework\Model\Context $context,
        \Magento\Framework\Registry $registry,
        \Magento\Framework\Data\FormFactory $formFactory,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
     \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
     \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
       \Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
        \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->condCombineFactory = $condCombineFactory;
        $this->condProdCombineF = $condProdCombineF;
        parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
    }
    /**
     * Set resource model and Id field name
     *
     * @return void
     */
    protected function _construct()
    {
        parent::_construct();
        $this->_init('Vendor\Module\Model\ResourceModel\Rule');
        $this->setIdFieldName('rule_id');
    }
    /**
     * Get rule condition combine model instance
     *
     * @return \Magento\SalesRule\Model\Rule\Condition\Combine
     */
      public function getConditionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    /**
     * Get rule condition product combine model instance
     *
     * @return \Magento\SalesRule\Model\Rule\Condition\Product\Combine
     */
    public function getActionsInstance()
    {
        return $this->condProdCombineF->create();
    }
    /**
     * Check cached validation result for specific address
     *
     * @param Address $address
     * @return bool
     */
    public function hasIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? true : false;
    }
    /**
     * Set validation result for specific address to results cache
     *
     * @param Address $address
     * @param bool $validationResult
     * @return $this
     */
    public function setIsValidForAddress($address, $validationResult)
    {
        $addressId = $this->_getAddressId($address);
        $this->validatedAddresses[$addressId] = $validationResult;
        return $this;
    }
    /**
     * Get cached validation result for specific address
     *
     * @param Address $address
     * @return bool
     * @SuppressWarnings(PHPMD.BooleanGetMethodName)
     */
    public function getIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? $this->validatedAddresses[$addressId] : false;
    }
    /**
     * Return id for address
     *
     * @param Address $address
     * @return string
     */
    private function _getAddressId($address)
    {
        if ($address instanceof Address) {
            return $address->getId();
        }
        return $address;
    }
}

Наконец-то я это сделал, вот мой обновленный код

public function execute()
    {  
      $validate  = array();
      $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
      $quoteId = $this->cart->getQuote()->getId();
      $quote =  $this->quoteFactory->load($quoteId);
      $fakeQuote = clone $quote;
      $fakeQuote->setId(null);
       $items = $this->cart->getQuote()->getAllItems();
       $rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();
      foreach ($rules as $rule){
          foreach($items as $item){
            $productId = $item->getProductId();
            $product = $objectManager->create('Magento\Catalog\Model\Product')->load($productId);
            $quoteItem = $objectManager->create('Magento\Quote\Model\Quote\Item');
            $quoteItem->setQuote($fakeQuote)->setProduct($product);
            $quoteItem->setAllItems(array($product));
            $quoteItem->getProduct()->setProductId($product->getEntityId());
            $validate = $rule->getConditions()->validate($quoteItem);
        } 
    }
   // var_dump($validate); 
    return $validate;
    }
Author: Divya Sekar, 2019-12-12

3 answers

Похоже, что вы проверяете свою модель (продукт) с помощью действий, но логически вы должны использовать условия, такие как:

$rule->getConditions()->validate($item);

Вот полный код с изменениями:

$product_id = '3';  // Crown Summit Backpack sku is 24-MB03
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();
foreach ($rules as $rule) {
    $product = $objectManager->get('Magento\Catalog\Model\Product')->load($product_id);
    $item = $objectManager->create('Magento\Catalog\Model\Product');
    $item->setProduct($product);
    $validate = $rule->getConditions()->validate($item);
}
var_dump($validate);
var_dump($product);

Я думаю, что getActions() является условием для Применения правила к (см. Выбор ниже вашего основного блока) или другим условиям в вашей модели.

Вы можете довольно просто определить, что вы используете для проверки, просто распечатайте $rule->getConditions()->asStringRecursive() и $rule->getActions()->asStringRecursive(). Вы должны увидеть, какой метод возвращает желаемое условия.

PS: $rule->getActions()->validate($item); всегда возвращает true, потому что пустые условия всегда означают , что любой элемент действителен.

 2
Author: Siarhey Uchukhlebau, 2019-12-12 12:45:07

Наконец-то я это сделал, вот мой обновленный код

public function execute()
    {  
      $validate  = array();
      $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
      $quoteId = $this->cart->getQuote()->getId();
      $quote =  $this->quoteFactory->load($quoteId);
      $fakeQuote = clone $quote;
      $fakeQuote->setId(null);
       $items = $this->cart->getQuote()->getAllItems();
       $rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();
      foreach ($rules as $rule){
          foreach($items as $item){
            $productId = $item->getProductId();
            $product = $objectManager->create('Magento\Catalog\Model\Product')->load($productId);
            $quoteItem = $objectManager->create('Magento\Quote\Model\Quote\Item');
            $quoteItem->setQuote($fakeQuote)->setProduct($product);
            $quoteItem->setAllItems(array($product));
            $quoteItem->getProduct()->setProductId($product->getEntityId());
            $validate = $rule->getConditions()->validate($quoteItem);
        } 
    }
   // var_dump($validate); 
    return $validate;
    }
 1
Author: Divya Sekar, 2020-09-11 12:55:53

Попробуйте использовать товары в корзине, используя приведенный ниже код

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$cart = $objectManager->get('\Magento\Checkout\Model\Cart');
$items = $cart->getQuote()->getAllItems();

$rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();

foreach($items as $item) {
    $validate = $rule->getActions()->validate($item);
}
var_dump($validate);
var_dump($product);            
 0
Author: Ranganathan, 2019-12-13 06:57:55