为什么magento的rewrite方法对抽象类无效

     magento中,是没法通过Mage::getModel("xx/xx")配合xml中的<rewrite>实现abstruct class的rewrite。 为什么?这需要详细了解一下magento中model的rewrite原理。
    

     假设xml中我们定义了如下的rewrite:

        	<customer>
        		<rewrite>
        			<customer>Newjueqi_Customer_Model_Customer</customer>
        		</rewrite>
        	</customer>

    根据配置,我们是把 Mage_Customer_Model_Customer rewrite为 Newjueqi_Customer_Model_Customer。
    那么,在执行 Mage::getModel('customer/customer') 时,magento到底做了什么?我们分析一下源码:

    1. 首先来到getmodel方法

    public static function getModel($modelClass = '', $arguments = array())
    {
	    //获取class实例
        return self::getConfig()->getModelInstance($modelClass, $arguments);
    }

     2. 看一下magento是怎么生成实例的

    public function getModelInstance($modelClass='', $constructArguments=array())
    {
	//获取类的名称,rewrite的关键就在与怎么把原来要生成的类名Mage_Customer_Model_Customer 换成 Newjueqi_Customer_Model_Customer。
        $className = $this->getModelClassName($modelClass);
        if (class_exists($className)) {
            Varien_Profiler::start('CORE::create_object_of::'.$className);
			
            //通过new的方法来产生一个类的实例
            $obj = new $className($constructArguments);
						
            Varien_Profiler::stop('CORE::create_object_of::'.$className);
            return $obj;
        } else {
            /* throw Mage::exception(
                'Mage_Core',
                Mage::helper('core')->__('Model class does not exist: %s.', $modelClass)
            ); */
            return false;
        }
    }


3. 好,最后看一下magento是怎么把生成的类名Mage_Customer_Model_Customer 换成 Newjueqi_Customer_Model_Customer。

    //对类名检验
    public function getModelClassName($modelClass)
    {
        $modelClass = trim($modelClass);
        if (strpos($modelClass, '/')===false) {
            return $modelClass;
        }
        return $this->getGroupedClassName('model', $modelClass);
    }	
	
    //获取所生成class的实际类名
    public function getGroupedClassName($groupType, $classId, $groupRootNode=null)
    {
        if (empty($groupRootNode)) {
            $groupRootNode = 'global/'.$groupType.'s';
        }

        $classArr = explode('/', trim($classId));
        $group = $classArr[0];
        $class = !empty($classArr[1]) ? $classArr[1] : null;

        if (isset($this->_classNameCache[$groupRootNode][$group][$class])) {
            return $this->_classNameCache[$groupRootNode][$group][$class];
        }

        $config = $this->_xml->global->{$groupType.'s'}->{$group};

        // First - check maybe the entity class was rewritten
        $className = null;
		
	/*
	$className = (string)$config->rewrite->$class;
	这里就是rewrite最关键的地方,magento已经在xml中找到“customer/customer”,
	接着magento会找一下<customer>标签下是否有<rewrite>标签,如果找到的话,就会把rewrite标签中的类名替换实际类名
		
		<customer>
        	  <rewrite>
        	     <customer>Newjueqi_Customer_Model_Customer</customer>
        	  </rewrite>
        	</customer>
			
	从上面的xml配置可知,是把“customer/customer”确定为Newjueqi_Customer_Model_Customer
         */
        if (isset($config->rewrite->$class)) {
            $className = (string)$config->rewrite->$class;
        } else {
            /**
             * Backwards compatibility for pre-MMDB extensions.
             * In MMDB release resource nodes <..._mysql4> were renamed to <..._resource>. So <deprecatedNode> is left
             * to keep name of previously used nodes, that still may be used by non-updated extensions.
             */
            if ($config->deprecatedNode) {
                $deprecatedNode = $config->deprecatedNode;
                $configOld = $this->_xml->global->{$groupType.'s'}->$deprecatedNode;
                if (isset($configOld->rewrite->$class)) {
                    $className = (string) $configOld->rewrite->$class;
                }
            }
        }

        // Second - if entity is not rewritten then use class prefix to form class name
        if (empty($className)) {
            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;
    }

看了上面的源码分析,我们可总结一下magento的rewrite机制:
1. 在xml文件中构造Mage::getModel('xxx/xxx')中所对应'xxx/xxx'所对应的实际类名,如果<rewrite>标签存在就使用<rewrite>标签中的类名,否则就用实际类名。
2. 使用$obj = new $className($constructArguments) 生成类的实例。

 由以上的分析可知,magento的rewrite最后是调用 new 来生成一个类的实例,但在php中,abstruct class是没法生成类的实例的,所以abstruct class是没法rewrite。

【文章作者】曾健生

【作者邮箱】zengjiansheng1@126.com

【作者QQ】190678908

【作者博客】blog.csdn.net/newjueqi






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

newjueqi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值