A bit of history
On 5th of September I sent out a tweet:
Guys, this is serious. I guess, I just resolved Magento’s single intheritance problem by using traits. Details later. #magento #worksforme.
Those who have been serious in hacking Magento and 3rd party extensions know well what I’m talking about. But please let me explain further.
Magento extension rewrite conflicts
You have a Magento instance. You have created a custom module My_Custom that happens to rewrite a core model, let’s say Mage_Catalog_Model_Product. So you have following lines in your module’s config.xml:
Then you have have a 3rd party extension that rewrites the same core class. You’re stuck now? Not quite. You now have 3 good methods to fix the problem. So good so far. But then you need another 3rd party extension that does the same – rewrites catalog/product. Now you’re stuck, right!?
You cannot make your code extend the 1st extension because the the second wouldn’t work and you cannot make yours to extend the second either because the 1st wouldn’t work then. Chicken and egg problem or “nokk kinni, saba lahti” as we say in Estonian.
The solution – PHP 5 feature “traits”
The idea is to make only My_Custom_Model_Product to rewrite catalog/product or at least to be the first one selected for rewrites. The other 2 3rd party module classes would just extend it and be used inside my product model via traits.
Add dependencies to your module
Add traits
My/Custom/Trait/Extension/B/Model/Product.php
Trait for Extension_A_Model_Product
Trait for Extension_B_Model_Product
Add traits to My_Custom_Model_Product
Voilaa!:) Now you have all the 3rd party module functionality available in your extension. When Magento is calling getModel(‘catalog/product’) it will actually load My_Custom_Model_Product. My_Custom_Model_Product extends Mage_Catalog_Model_Product and it also exposes all methods from Extension_A_Model_Product and Extension_B_Model_Product.
A note about traits
With traits you can avoid duplicating original class method implementation’s part. You’ll just create a proxy for original class method’s thru the trait. However you need to maintain the traits whenever Extension_A or Extension_B are upgraded or changed. So you should document it that you created traits and solved multiple rewrite problem this way. Then you can look up the documentation when doing upgrade to extensions next time.
As always – feedback is welcome!