Rewriting a Model Class

来源:互联网 发布:药家鑫 知乎 编辑:程序博客网 时间:2024/05/17 23:01

One of the best ways to extend the capabilities of the Magneto core is to "rewrite" their classes. If create a new instance of a model class the way you are supposed to (Mage::getModel('awesome/example)), Magento has built in a handy way of being able to "rewrite" your request from model A to model B.

Let's say that you have a business requirement to always show the phrase "loves Magento" after you display the customer name. To do this, you can find every place that outputs the customer name, OR change the way the customer name is gotten. For this example, we will do the latter.

First we need to create our new class:

?
1
2
3
4
5
6
7
8
9
10
11
class Super_Awesome_Model_Customer extends Mage_Customer_Model_Customer
{
 
    publicfunction getName()
    {
        $name= parent::getName();
        $name= $name . ' loves Magento';
        return$name;
    }
 
}

Next, we need a way to tell Magento to use OUR class instead of the one it normally does. So, all over the place in Magento, you will find: Mage::getModel('customer/customer'). This will use the config.xml in the Mage_Customer module to build the class name Mage_Customer_Model_Customer. To get it to use ours instead we will put a rewrite into the config.xml. You can put this rewrite into ANY config.xml, but we will put it in the Super_Awesome module.

?
1
2
3
4
5
6
7
8
9
<global>
       <models>
           <customer>
               <rewrite>
                   <customer>Super_Awesome_Model_Customer</customer>
               </rewrite>
           </customer>
       </models>
 </global>
Mage::getModel('customer/customer')                  |           |_ Is the <customer> tag inside the <rewrite> element.                  |_ Is the <customer> tag outside the <rewrite> element.

So now when you make a call for Mage::getModel('customer/customer'), Magento will FIRST check if there is a rewrite for that class alias and will return an instance of the Super_Awesome_Model_Customer model instead of Mage_Customer_Model_Customer.

If you were trying to rewrite Mage_Customer_Model_Customer_Api to Super_Awesome_Model_Example_Of_Customer_Api, you would add the rewrite:

?
1
2
3
4
5
6
7
8
9
<global>
       <models>
           <customer>
               <rewrite>
                   <customer_api>Super_Awesome_Model_Example_Of_Customer_Api</customer_api>
               </rewrite>
           </customer>
       </models>
 </global>

If you want to take a look at how Magento checks for rewrites, take a look in Mage_Core_Model_Config->getGroupedClassName():

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$config = $this->_xml->global->{$groupType.'s'}->{$group};
 
if (isset($config->rewrite->$class)) {
    $className= (string)$config->rewrite->$class;
} else{
    if(!empty($config)) {
        $className= $config->getClassName();
    }
    if(empty($className)) {
        $className= 'mage_'.$group.'_'.$groupType;
    }
    if(!empty($class)) {
        $className.= '_'.$class;
    }
    $className= uc_words($className);
}
 
$this->_classNameCache[$groupRootNode][$group][$class] = $className;
return $className;

Important Note: You cannot rewrite a model class unless it is created by using the Mage::getModel(). So if you have a class like Mage_Customer_Model_Address that extends Mage_Customer_Model_Address_Abstract and you want to rewrite the Mage_Customer_Model_Address_Abstract class to do something different, you are out of luck on the rewrite option. You would need to copy Mage_Customer_Model_Address_Abstract down into your local code pool.