In this lesson, we will learn how to override core files in magento. In reality, when developing a project, we rarely use a framework without changing it. However, these changes are not recommended because of its effect on the whole project.
The focus of today’s lesson is about how to solve this issue and find a way to override core files which does not affect the other. Follow us in Magento Tutorial.
Lesson 18 takes about three hours and is divided into two parts:
- Overriding principle in magento
- Overriding in Magento (Block, Model, ResourceModel, Helper)
1. Overriding principle in magento
The overriding principle in magento is very simple, it is basically rewriting available functions in core to meet the user’s purpose.
The rewrite of Models / Resource models/ Helper/ Block only applies to objects called through Mage, such as Mage::getModel(), Mage::getResourceModel(), Mage::helper(), Mage::getSingletonBlock(). This rewrite does not work with other ways of creating object such as new ($product = new Mage_Catalog_Model_Product();) or extends. This is the difference when we call for an object either directly from its class name or using functions that Magento provides.
2. Overriding in Magento (Block, Model, ResourceModel, Helper)
2.1. Override Block Class
Suppose that we want to offer a 20% discount on goods in the opening ceremony. To do that, we overrideclass Mage_Catalog_Block_Product_List and show the special price of goods. Firstly, we will declare that we override the above class by adding the following code block into tags <blocks><blocks> in file config.xml:
<config> <global> <blocks> <lesson18> <class>Magestore_Lesson18_Block</class> </lesson18> <catalog> <rewrite> <product_list> Magestore_Lesson18_Block_Catalog_Product_List </product_list> </rewrite> </catalog> </blocks> </global> </config>
As you can see, we write “rewrite” tag inside “catalog” tag. “Catalog” tag implies app/code/core/Mage/Catalog/. Then, “rewrite” tag informs the system of overriding block. <product_list> tag directs to app/code/core/Mage/Catalog/Product /List.php and this tag contains the class name used to override block class.
Next, we create a file app/code/local/Magestore/Lesson18/Block/Catalog/Product/List.php that contains class Magestore_Lesson18_Block_Catalog_Product_List that we have just declared above. In reality, we can place this file anywhere in folder Block of Module, but we should use structure file/folder as the structure file/folder in Magento core.
Class Magestore_Lesson18_Block_Catalog_Product_List will extend class Mage_Catalog_Block_Product_List. The purpose of this extension is to help reuse the functions of system we do not rewrite.
class Magestore_Lesson18_Block_Catalog_Product_List extends Mage_Catalog_Block_Product_List{ // function that need to rewrite protected function _getProductCollection(){ parent::_getProductCollection(); //Define discount percent $percentDiscount = 20; foreach($this->_productCollection as $product) { $price = $product->getPrice(); $finalPriceNow = $product->getData('final_price'); $specialPrice = $price - $price * $percentDiscount / 100; // if special price is negative - negate the discount - this may be a mistake in data if ($specialPrice < 0) $specialPrice = $finalPriceNow; if ($specialPrice < $finalPriceNow) $product->setFinalPrice($specialPrice); // set the product final price } return $this->_productCollection; } }
The result is shown as below:
2.2. Override Model Class
In the above section, we succeed in showing the special price in the product listing page. However, it fails to show in the product detailed page.
So, how to solve this problem? Simply override model class.
Overriding model class and overriding block class have many things in common. The following steps give you the instructions on how to override block class:
STEP 1: Declare in file config.xml
<config></span> <span style="font-family: georgia, palatino, serif;"> <global></span> <span style="font-family: georgia, palatino, serif;"> <models></span> <span style="font-family: georgia, palatino, serif;"> <lesson18></span> <span style="font-family: georgia, palatino, serif;"> <class>Magestore_Lesson18_Model</class></span> <span style="font-family: georgia, palatino, serif;"> </lesson18></span> <span style="font-family: georgia, palatino, serif;"> <catalog></span> <span style="font-family: georgia, palatino, serif;"> <rewrite></span> <span style="font-family: georgia, palatino, serif;"> <product_type_price></span> <span style="font-family: georgia, palatino, serif;"> Magestore_Lesson18_Model_Product_Type_Price</span> <span style="font-family: georgia, palatino, serif;"> </product_tye_price></span> <span style="font-family: georgia, palatino, serif;"> </rewrite></span> <span style="font-family: georgia, palatino, serif;"> </catalog></span> <span style="font-family: georgia, palatino, serif;"> </models></span> <span style="font-family: georgia, palatino, serif;"> </global></span> <span style="font-family: georgia, palatino, serif;"> </config>
STEP 2: Create file Magestore/Lesson18/Model/Product/Price.php which contains class Magestore_Lesson18_Model_Product_Type_Price to override as declared in file config:
class Magestore_Lesson18_Model_Product_Type_Price extends Mage_Catalog_Model_Product_Type_Price</span> <span style="font-family: georgia, palatino, serif;"> {</span> <span style="font-family: georgia, palatino, serif;"> public function getFinalPrice($qty=null, $product){</span> <span style="font-family: georgia, palatino, serif;"> if (is_null($qty) && !is_null($product->getCalculatedFinalPrice())) {</span> <span style="font-family: georgia, palatino, serif;"> return $product->getCalculatedFinalPrice();</span> <span style="font-family: georgia, palatino, serif;"> }</span> <span style="font-family: georgia, palatino, serif;">$finalPrice = $this->getBasePrice($product, $qty);</span> <span style="font-family: georgia, palatino, serif;"> $product->setFinalPrice($finalPrice);</span> <span style="font-family: georgia, palatino, serif;">Mage::dispatchEvent('catalog_product_get_final_price', array('product' => $product, 'qty' => $qty));</span> <span style="font-family: georgia, palatino, serif;">$finalPrice = $product->getData('final_price');</span> <span style="font-family: georgia, palatino, serif;"> $finalPrice = $this->_applyOptionsPrice($product, $qty, $finalPrice);</span> <span style="font-family: georgia, palatino, serif;"> $finalPrice = max(0, $finalPrice);</span> <span style="font-family: georgia, palatino, serif;"> //Define discount percent</span> <span style="font-family: georgia, palatino, serif;"> $percentDiscount = 20;</span> <span style="font-family: georgia, palatino, serif;"> //Set final price for product</span> <span style="font-family: georgia, palatino, serif;"> $finalPrice = $finalPrice * (1-$percentDiscount/100);</span> <span style="font-family: georgia, palatino, serif;"> $product->setFinalPrice($finalPrice);</span> <span style="font-family: georgia, palatino, serif;">return $finalPrice;</span> <span style="font-family: georgia, palatino, serif;"> }</span> <span style="font-family: georgia, palatino, serif;"> }
The result is shown as below:
2.3. Override Helper Class
With the above sale-off project, only customers who have account on your site can buy products. People who visit site as guests are not allowed to check out. We override helper class Mage_CheckoutHelper_Data.
Checkout method form before being overridden:
Like declaration of overriding block class and model class, we will declare helper class Mage_Checkout_Helper_Data as follows:
<config></span> <span style="font-family: georgia, palatino, serif;"> <global></span> <span style="font-family: georgia, palatino, serif;"> <helpers></span> <span style="font-family: georgia, palatino, serif;"> <lesson18></span> <span style="font-family: georgia, palatino, serif;"> <class>Magestore_Lesson18_Model</class></span> <span style="font-family: georgia, palatino, serif;"> </lesson18></span> <span style="font-family: georgia, palatino, serif;"> <checkout></span> <span style="font-family: georgia, palatino, serif;"> <rewrite></span> <span style="font-family: georgia, palatino, serif;"> <data>Magestore_Lesson18_Helper_Checkout_Data</data></span> <span style="font-family: georgia, palatino, serif;"> </rewrite></span> <span style="font-family: georgia, palatino, serif;"> </checkout></span> <span style="font-family: georgia, palatino, serif;"> </helpers></span> <span style="font-family: georgia, palatino, serif;"> </global></span> <span style="font-family: georgia, palatino, serif;"> </config>
Override helper class:
class Magestore_Lesson18_Helper_Checkout_Data extends Mage_Checkout_Helper_Data</span> <span style="font-family: georgia, palatino, serif;"> {</span> <span style="font-family: georgia, palatino, serif;"> public function isAllowedGuestCheckout(Mage_Sales_Model_Quote $quote, $store = null)</span> <span style="font-family: georgia, palatino, serif;"> {</span> <span style="font-family: georgia, palatino, serif;"> return false;</span> <span style="font-family: georgia, palatino, serif;"> }</span> <span style="font-family: georgia, palatino, serif;"> }
Here is the result:
2.4. Override Resource Model
Overriding resource model class is slightly different from the three classes mentioned. The difference is in file config.xml. A resource model is put in folder “Mysq14” and declared in file config.xml using tag <resourceModel></resourceModel>.
Instead of declaring only <catalog> tag before <rewrite> tag, you need to declare the whole link to folder mysq14.
Suppose that we want to override class Mage_Review_Model_Resource_Review_Collection, we will declare in file config.xml as follows:
<config></span> <span style="font-family: georgia, palatino, serif;"> <global></span> <span style="font-family: georgia, palatino, serif;"> <models></span> <span style="font-family: georgia, palatino, serif;"> <lesson18></span> <span style="font-family: georgia, palatino, serif;"> <class> Magestore_Lesson18_Model</class></span> <span style="font-family: georgia, palatino, serif;"> </lesson18></span> <span style="font-family: georgia, palatino, serif;"> <review_resource ></span> <span style="font-family: georgia, palatino, serif;"> <rewrite></span> <span style="font-family: georgia, palatino, serif;"> <review_collection></span> <span style="font-family: georgia, palatino, serif;"> Magestore_Lesson18_Model_Review_Resource_Review_Collection</span> <span style="font-family: georgia, palatino, serif;"> </review_collection></span> <span style="font-family: georgia, palatino, serif;"> </rewrite></span> <span style="font-family: georgia, palatino, serif;"> </review_resource ></span> <span style="font-family: georgia, palatino, serif;"> </models></span> <span style="font-family: georgia, palatino, serif;"> </global></span> <span style="font-family: georgia, palatino, serif;"> </config>
Then, override class in the same way as overriding class in model:
class Magestore_Lesson18_Model_Review_Resource_Review extends Mage_Review_Model_Resource_Review_Collection {</span> <span style="font-family: georgia, palatino, serif;"> protected function _initSelect() {</span> <span style="font-family: georgia, palatino, serif;"> parent::_initSelect();</span> <span style="font-family: georgia, palatino, serif;"> $this->getSelect()</span> <span style="font-family: georgia, palatino, serif;"> ->join(array('detail' => $this->_reviewDetailTable), 'main_table.review_id = detail.review_id', array('title', 'detail', 'nickname', 'size'));</span> <span style="font-family: georgia, palatino, serif;"> return $this;</span> <span style="font-family: georgia, palatino, serif;"> }</span> <span style="font-family: georgia, palatino, serif;"> }
So, the lesson 18 ends here. After learning this lesson, we should know overriding principle in Magento and h over how to override in Magento.
Good luck and see you again! Follow us in Magento Open Course for Magento Tutorial.
1 Comment
Nice description. Awesome.