In Magento there is a sufficient number of complex data processes, which may take quite a long time and consume a large amount of server memory and performance, especially if the database contains a huge pool of data (products, categories, customers, orders, etc). The indexing of products attributes, categories, prices, etc may serve as an example of such a process. But into this list we can also include one more process – the application of catalog price rules (apply rules):
If your directory has a big list of products and pricing rules, the Apply Rules process most probably will not be able to complete, but instead will take a lot of time and effort.
The application of price rules works as follows: we have a collection of all active rules and they all perform their own Apply command in a loop, and after the cycle the reindexing of catalog prices is implemented.
I suggest implementing every rule as a separate shell-command to reduce the memory consumption by the number equal to the number of price rules. And then run the indexation as a separate shell-command too.
For this we will create a shell file which will execute the aforementioned commands in sequence. The file will look as follows:
1 2 3 4 5 6 |
php applyRulesByOne.php start for i in `cat ruleIds` do php applyRulesByOne.php $i done php applyRules.php |
As you see, we have two php scripts. The first аpplyRulesByOne.php script contains the parameter start and generates the list of all active price rules and stores their IDs into the ruleIds file. If the parameter start is replaced with a number, then the script is looking for the rule with the ID equal to that number and executes this rule.
The Script аpplyRules.php cleans cache and starts the indexation of directory prices.
So, if we take a closer look at our shell file, you will notice that it primarily generates IDs of all active price rules and launches the shell-command for its single execution. After that the indexation is called and cache gets cleared.
My shell-file is launched by a cron-job so now I am not worried that my store may have any problems with discounts :)
The source code of the аpplyRulesByOne.php file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<?php require_once(dirname(__file__) . '/../app/Mage.php'); Mage::init(); Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); class CustomRulesApplyer extends Mage_CatalogRule_Model_Rule { public function applyByRule($rule) { return $this->_getResource()->updateRuleProductData($rule); } } $action = (isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : false); if ($action == 'start') { echo 'Start...'; $ids = array(); $_rules = Mage::getModel('catalogrule/rule')->getCollection(); foreach ($_rules as $rule) { $ids[] = $rule->getId(); } file_put_contents(dirname(__FILE__) . '/ruleIds', (string)implode(chr(10), $ids)); die(); } if ((int)$action) { $rules = new CustomRulesApplyer; $_rule = Mage::getModel('catalogrule/rule')->load($action); if ($_rule->getId()) { echo chr(10) . 'Start #' . $_rule->getId(); file_put_contents(dirname(__FILE__) . '/apllRep', (string)$_rule->getId()); $rules->applyByRule($_rule); die(' Done ' . $_rule->getId()); } } |
The source code of the file applyRules.php:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<?php require_once(dirname(__file__) . '/../app/Mage.php'); Mage::init(); Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); class CustomRulesApplyer extends Mage_CatalogRule_Model_Rule { public function applyAll() { echo 'applyAllRules...'; $this->_getResource()->applyAllRules(); echo '_invalidateCache...'; $this->_invalidateCache(); echo 'indexProcess...'; $indexProcess = Mage::getSingleton('index/indexer') ->getProcessByCode('catalog_product_price'); if ($indexProcess) { $indexProcess->reindexAll(); } } } $rules = new CustomRulesApplyer; echo 'Finish...'; $rules->applyAll(); die(''); |
All of these files are located in the Magento root folder. This is indicated in this line:
1 |
require_once(dirname(__file__) . '/../app/Mage.php'); |
Conclusion! Such approach makes it possible to implement heavy scripts that are processing data in a loop.
Find one more solution here.
Hi Eugeny,
Thank you for your comment!
My article was written for Magento 1.7 or 1.6, much water has flown under the bridge since that time…
It seems like Magento 1.9.3.2 hasn’t method applyAllRules and Fatal Error happens because of that. Please get in touch with our support team at [email protected] and they will discuss with you solution that will work on your Magento version.
Thank you for your solution. But i have a problem: i try to use code described above and see that error after
Finish...
:Finish…applyAllRules…PHP Fatal error: Call to undefined method Mage_CatalogRule_Model_Resource_Rule::applyAllRules() in /home/ivoltinvest/web/domain.com/public_html/shell/applyRules.php on line 13
Magento version is 1.9.3.2. Can you help me? Thanks.
Hi Alex,
Thanks for the feedback, you are welcome!
Thanks for sharing this video tutorial, I was working to set catalog price rules in my Magento store, Your vide and this post helped me a lot.
Hi John,
as it’s said above, all of the files are located in the Magento root folder. So, you should place the script there as well.
where do i place the scell script?
Also check out the logic inside of Mage_CatalogRule_Model_Rule::callbackValidateProduct() if you have a lot of websites. Magento is checking products on all websites, even if your rule only applies to a single website.
would this work on magento 1.9.2.1 ? Can you provide instructions to add it as a cron job? I get an error
Could not open input file: applyRulesByOne.php
Could not open input file: applyRulesByOne.php
Could not open input file: applyRules.php
when my cron is executed