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
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