How to get maching products based on rule conditions

The question:

how to get matching products based on rule conditions i need to filter product grid according to rule condition in my custom module I have used it as a filter

enter image description here

Array
(
    [conditions] => Array
        (
            [1] => Array
                (
                    [type] => MagentoCatalogRuleModelRuleConditionCombine
                    [aggregator] => all
                    [value] => 1
                    [new_child] => 
                )

            [1--1] => Array
                (
                    [type] => MagentoCatalogRuleModelRuleConditionProduct
                    [attribute] => attribute_set_id
                    [operator] => ==
                    [value] => 15
                )

            [1--2] => Array
                (
                    [type] => MagentoCatalogRuleModelRuleConditionProduct
                    [attribute] => price
                    [operator] => <
                    [value] => 2000
                )

        )

)

I have this array of rule conditions and I need products based on conditions

The Solutions:

Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.

Method 1

finally I found the solution.

/*Controller code */

    $modelRule = $this->_objectManager->create('NameSpaceModuleNameModelRule');
                $data = $this->prepareData($data);
                $modelRule->loadPost($data);
    $productIds = $modelRule->getListProductIds();


    protected function prepareData($data)
        {
            if (isset($data['rule']['conditions'])) {
                $data['conditions'] = $data['rule']['conditions'];
            }
            unset($data['rule']);
            return $data;
        }

NameSpaceModuleNameModelRule.php

    namespace NameSpaceModuleNameModel;

    class Rule extends MagentoCatalogRuleModelRule {
        /**
         * Prefix of model events names
         *
         * @var string
         */
        protected $_eventPrefix = 'catalogrule_rule';

        /**
         * Parameter name in event
         *
         * In observe method you can use $observer->getEvent()->getRule() in this case
         *
         * @var string
         */
        protected $_eventObject = 'rule';

        /**
         * Store matched product Ids
         *
         * @var array
         */
        protected $_productIds;

        /**
         * Limitation for products collection
         *
         * @var int|array|null
         */
        protected $_productsFilter = null;

        /**
         * Store current date at "Y-m-d H:i:s" format
         *
         * @var string
         */
        protected $_now;

        /**
         * Cached data of prices calculated by price rules
         *
         * @var array
         */
        protected static $_priceRulesData = [];

        /**
         * Catalog rule data
         *
         * @var MagentoCatalogRuleHelperData
         */
        protected $_catalogRuleData;

        /**
         * @var MagentoFrameworkAppCacheTypeListInterface
         */
        protected $_cacheTypesList;

        /**
         * @var array
         */
        protected $_relatedCacheTypes;

        /**
         * @var MagentoFrameworkStdlibDateTime
         */
        protected $dateTime;

        /**
         * @var MagentoFrameworkModelResourceModelIterator
         */
        protected $_resourceIterator;

        /**
         * @var MagentoCustomerModelSession
         */
        protected $_customerSession;

        /**
         * @var MagentoCatalogRuleModelRuleConditionCombineFactory
         */
        protected $_combineFactory;

        /**
         * @var MagentoCatalogRuleModelRuleActionCollectionFactory
         */
        protected $_actionCollectionFactory;

        /**
         * @var MagentoCatalogModelProductFactory
         */
        protected $_productFactory;

        /**
         * @var MagentoStoreModelStoreManagerInterface
         */
        protected $_storeManager;

        /**
         * @var MagentoCatalogModelResourceModelProductCollectionFactory
         */
        protected $_productCollectionFactory;

        /**
         * @var MagentoCatalogRuleModelIndexerRuleRuleProductProcessor;
         */
        protected $_ruleProductProcessor;

        /**
         * @var DataConditionConverter
         */
        protected $ruleConditionConverter;

        /**
         * Rule constructor.
         * @param MagentoFrameworkModelContext $context
         * @param MagentoFrameworkRegistry $registry
         * @param MagentoFrameworkDataFormFactory $formFactory
         * @param MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate
         * @param MagentoCatalogModelResourceModelProductCollectionFactory $productCollectionFactory
         * @param MagentoStoreModelStoreManagerInterface $storeManager
         * @param RuleConditionCombineFactory $combineFactory
         * @param RuleActionCollectionFactory $actionCollectionFactory
         * @param MagentoCatalogModelProductFactory $productFactory
         * @param MagentoFrameworkModelResourceModelIterator $resourceIterator
         * @param MagentoCustomerModelSession $customerSession
         * @param MagentoCatalogRuleHelperData $catalogRuleData
         * @param MagentoFrameworkAppCacheTypeListInterface $cacheTypesList
         * @param MagentoFrameworkStdlibDateTime $dateTime
         * @param IndexerRuleRuleProductProcessor $ruleProductProcessor
         * @param MagentoFrameworkModelResourceModelAbstractResource|null $resource
         * @param MagentoFrameworkDataCollectionAbstractDb|null $resourceCollection
         * @param array $relatedCacheTypes
         * @param array $data
         *
         * @SuppressWarnings(PHPMD.ExcessiveParameterList)
         */

        public function __construct(
        MagentoFrameworkModelContext $context,
        MagentoFrameworkRegistry $registry,
        MagentoFrameworkDataFormFactory $formFactory,
        MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate,
        MagentoCatalogModelResourceModelProductCollectionFactory $productCollectionFactory,
        MagentoStoreModelStoreManagerInterface $storeManager,
        MagentoCatalogRuleModelRuleConditionCombineFactory $combineFactory,
        MagentoCatalogRuleModelRuleActionCollectionFactory $actionCollectionFactory,
        MagentoCatalogModelProductFactory $productFactory,
        MagentoFrameworkModelResourceModelIterator $resourceIterator,
        MagentoCustomerModelSession $customerSession,
        MagentoCatalogRuleHelperData $catalogRuleData,
        MagentoFrameworkAppCacheTypeListInterface $cacheTypesList,
        MagentoFrameworkStdlibDateTime $dateTime,
        MagentoCatalogRuleModelIndexerRuleRuleProductProcessor $ruleProductProcessor,
        MagentoFrameworkModelResourceModelAbstractResource $resource = null,
        MagentoFrameworkDataCollectionAbstractDb $resourceCollection = null,
        array $relatedCacheTypes = [],
        array $data = []
        ) {

            parent::__construct(
                    $context,
                    $registry,
                    $formFactory,
                    $localeDate,
                    $productCollectionFactory,
                    $storeManager,
                    $combineFactory,
                    $actionCollectionFactory,
                    $productFactory,
                    $resourceIterator,
                    $customerSession,
                    $catalogRuleData,
                    $cacheTypesList,
                    $dateTime,
                    $ruleProductProcessor,
                    $resource,
                    $resourceCollection,
                    $relatedCacheTypes,
                    $data
            );
        }
        /**
         * Init resource model and id field
         *
         * @return void
         */
        protected function _construct()
        {
            parent::_construct();
            $this->_init('MagentoCatalogRuleModelResourceModelRule');
            $this->setIdFieldName('rule_id');
        }
        /**
         * Getter for rule conditions collection
         *
         * @return MagentoRuleModelConditionCombine
         */
        public function getConditionsInstance()
        {
            return $this->_combineFactory->create();
        }

        /**
         * Getter for rule actions collection
         *
         * @return MagentoCatalogRuleModelRuleActionCollection
         */
        public function getActionsInstance()
        {
            return $this->_actionCollectionFactory->create();
        }

        public function toArray(array $arrAttributes = array()) {
        return parent::toArray($arrAttributes);
        }

        public function getListProductIds()
        {    
         $productCollection = MagentoFrameworkAppObjectManager::getInstance()->create(
             'MagentoCatalogModelResourceModelProductCollection'
         );
         $productFactory = MagentoFrameworkAppObjectManager::getInstance()->create(
             'MagentoCatalogModelProductFactory'
         );
         $this->_productIds = [];
         $this->setCollectedAttributes([]);
         $this->getConditions()->collectValidatedAttributes($productCollection);
         MagentoFrameworkAppObjectManager::getInstance()->create(
             'MagentoFrameworkModelResourceModelIterator'
         )->walk(
             $productCollection->getSelect(),
             [[$this, 'callbackValidateProduct']],
             [
                 'attributes' => $this->getCollectedAttributes(),
                 'product' => $productFactory->create()
             ]
         );
        return $this->_productIds;
        }
        /**
        * Callback function for product matching
        *
        * @param array $args
        * @return void
        */
        public function callbackValidateProduct($args)
        {
         $product = clone $args['product'];
         $product->setData($args['row']);
         $websites = $this->_getWebsitesMap();
         foreach ($websites as $websiteId => $defaultStoreId) {
             $product->setStoreId($defaultStoreId);
             if ($this->getConditions()->validate($product)) {
                 $this->_productIds[] = $product->getId();
             }
         }
        }
        /**
        * Prepare website map
        *
        * @return array
        */
        protected function _getWebsitesMap()
        {
         $map = [];
         $websites = MagentoFrameworkAppObjectManager::getInstance()->create(
             'MagentoStoreModelStoreManagerInterface'
         )->getWebsites();
         foreach ($websites as $website) {
             // Continue if website has no store to be able to create catalog rule for website without store
             if ($website->getDefaultStore() === null) {
                 continue;
             }
             $map[$website->getId()] = $website->getDefaultStore()->getId();
         }
         return $map;
        }

    }

Method 2

Method-1 by using getConditions()->validate()

  protected $customConditionModel;
    protected $productFactory;
 
    public function __construct(
        ....................................................
        MagentoCatalogModelProductFactory $productFactory,
        VendoreNameAddConditionFiledModelCustomConditionFactory $customConditionModel,
        ....................................................
    ) {
        ....................................................
        $this->productFactory = $productFactory;
        $this->customConditionModel = $customConditionModel;
        ....................................................
    }
 
    public function checkCondition()
    {
        echo "<pre>";
        $prdId = 6; //bag product id
        // Get product data by id
        $prdData = $this->productFactory->create()->load($prdId);
        // get rule collection
        $ruleColl = $this->customConditionModel->create()->getCollection();
        foreach ($ruleColl as $ruleKey => $ruleVal) {
            // check Product with condition
            if ($ruleVal->getConditions()->validate($prdData)) {
                echo "Rule Id " . $ruleVal->getId() . " Match<br/>";
            }
        }
    }

Method-2 by using the Model function getMatchProductIds() which we already created.

protected $customConditionModel;

public function __construct(
    ....................................................
    VendoreNameAddConditionFiledModelCustomConditionFactory $customConditionModel,
    ....................................................
) {
    ....................................................
    $this->customConditionModel = $customConditionModel;
    ....................................................

}

public function checkCondition()
{
    echo "<pre>";
    // get rule collection
    $ruleColl = $this->customConditionModel->create()->getCollection();
    foreach ($ruleColl as $ruleKey => $ruleVal) {
        // get all product's Ids with match with rule
        echo "***** Rule Id " . $ruleVal->getId() . " Match Product Ids ***** <br/>";
        $matchIds = array_values(array_unique($ruleVal->getMatchProductIds()));
        print_r($matchIds);
    }
}

Model file give below:

<?php

namespace VendoreNameAddConditionFiledModel;

use VendoreNameAddConditionFiledModelResourceModelCustomCondition as CustomConditionResourceModel;
use MagentoQuoteModelQuoteAddress;
use MagentoRuleModelAbstractModel;

class CustomCondition extends AbstractModel
{
    protected $_eventPrefix = 'VendoreName_addconditionfiled';
    protected $_eventObject = 'rule';
    protected $condCombineFactory;
    protected $condProdCombineF;
    protected $validatedAddresses = [];
    protected $_selectProductIds;
    protected $_displayProductIds;

    public function __construct(
        MagentoFrameworkModelContext $context,
        MagentoFrameworkRegistry $registry,
        MagentoFrameworkDataFormFactory $formFactory,
        MagentoFrameworkStdlibDateTimeTimezoneInterface $localeDate,
        MagentoCatalogRuleModelRuleConditionCombineFactory $condCombineFactory,
        MagentoSalesRuleModelRuleConditionProductCombineFactory $condProdCombineF,
        MagentoFrameworkModelResourceModelAbstractResource $resource = null,
        MagentoFrameworkDataCollectionAbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->condCombineFactory = $condCombineFactory;
        $this->condProdCombineF = $condProdCombineF;
        parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
    }

    protected function _construct()
    {
        parent::_construct();
        $this->_init(CustomConditionResourceModel::class);
        $this->setIdFieldName('rule_id');
    }

    public function getConditionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    public function getActionsInstance()
    {
        return $this->condCombineFactory->create();
    }

    public function hasIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? true : false;
    }

    public function setIsValidForAddress($address, $validationResult)
    {
        $addressId = $this->_getAddressId($address);
        $this->validatedAddresses[$addressId] = $validationResult;
        return $this;
    }

    public function getIsValidForAddress($address)
    {
        $addressId = $this->_getAddressId($address);
        return isset($this->validatedAddresses[$addressId]) ? $this->validatedAddresses[$addressId] : false;
    }

    private function _getAddressId($address)
    {
        if ($address instanceof Address) {
            return $address->getId();
        }
        return $address;
    }

    public function getConditionsFieldSetId($formName = '')
    {
        return $formName . 'rule_conditions_fieldset_' . $this->getId();
    }

    public function getActionFieldSetId($formName = '')
    {
        return $formName . 'rule_actions_fieldset_' . $this->getId();
    }

    public function getMatchProductIds()
    {
        $productCollection = MagentoFrameworkAppObjectManager::getInstance()->create(
            'MagentoCatalogModelResourceModelProductCollection'
        );
        $productFactory = MagentoFrameworkAppObjectManager::getInstance()->create(
            'MagentoCatalogModelProductFactory'
        );
        $this->_selectProductIds = [];
        $this->setCollectedAttributes([]);
        $this->getConditions()->collectValidatedAttributes($productCollection);
        MagentoFrameworkAppObjectManager::getInstance()->create(
            'MagentoFrameworkModelResourceModelIterator'
        )->walk(
            $productCollection->getSelect(),
            [[$this, 'callbackValidateProductCondition']],
            [
                'attributes' => $this->getCollectedAttributes(),
                'product' => $productFactory->create(),
            ]
        );
        return $this->_selectProductIds;
    }

    public function callbackValidateProductCondition($args)
    {
        $product = clone $args['product'];
        $product->setData($args['row']);
        $websites = $this->_getWebsitesMap();
        foreach ($websites as $websiteId => $defaultStoreId) {
            $product->setStoreId($defaultStoreId);
            if ($this->getConditions()->validate($product)) {
                $this->_selectProductIds[] = $product->getId();
            }
        }
    }

    protected function _getWebsitesMap()
    {
        $map = [];
        $websites = MagentoFrameworkAppObjectManager::getInstance()->create(
            'MagentoStoreModelStoreManagerInterface'
        )->getWebsites();
        foreach ($websites as $website) {
            if ($website->getDefaultStore() === null) {
                continue;
            }
            $map[$website->getId()] = $website->getDefaultStore()->getId();
        }
        return $map;
    }
}

Check Full Example click Here.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Comment