Loading [MathJax]/jax/output/HTML-CSS/jax.js

Magento工厂名及函数

Magento Alan 11年前 (2014-07-03) 4663次浏览 0个评论 扫描二维码

Magento通过工厂方法(factory method)来实例化Model, Helper和Block类。一个工厂方法就是一种设计模式,用于通过一个类的别名来实例化一个对象,而无需使用具体的类别。
Magento采用了如下几个工厂方法:

  • Mage::getModel()
  • Mage::getResourceModel()
  • Mage::helper()
  • Mage::getSingleton()
  • Mage::getResourceSingleton()
  • Mage::getResourceHelper()

每个方法能通过类的别名来决定我们所要实例化的对象的真实类名,比如我们想要实例化product对象,可以通过调用getModel()方法来实现:

$product = Mage::getModel('catalog/product');

注意我们所传入的工厂名由group_classname/model_
name所组成,Magento会将其解析为一个真实的类名Mage_Catalog_Model_
Product。下面让我们来分析一下getModel()方法的内部机制:

1
2
3
4
5
6
7
8
9
10
11
public static function getModel($modelClass = '', $arguments =
 
array())
 
    {
 
    return self::getConfig()->getModelInstance
 
    ($modelClass, $arguments);
 
    }

getModel调用了Mage_Core_Model_Config类中的getModelInstance方法:

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
public function getModelInstance($modelClass='',
 
$constructArguments=array())
 
{
 
    $className = $this->getModelClassName($modelClass);
 
    if (class_exists($className)) {
 
        Varien_Profiler::start('CORE::create_object_of::'.$className);
 
        $obj = new $className($constructArguments);
 
        Varien_Profiler::stop('CORE::create_object_of::'.$className);
 
        return $obj;
 
    } else {
 
        return false;
 
    }
 
}

getModelInstance()又调用getModelClassName()方法,该方法将我们类的别名作一个参数,然后尝试验证所返回类是否存在,如果该类存在,则为该类创建一个实例并将其返回到getModel()方法中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public function getModelClassName($modelClass)
 
{
 
    $modelClass = trim($modelClass);
 
    if (strpos($modelClass, '/')===false) {
 
        return $modelClass;
 
    }
 
    return $this->getGroupedClassName('model', $modelClass);
 
}

getModelClassName()调用getGroupedClassName()方法(/app/code/core/Mage/Core/Model/Config.php),该方法用于返回模型中真实的类别。getGroupedClassName()中有groupTypeclassId两个参数,groupType(model,blockhelper)classId就是我们所要实例化的类。

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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;
 
        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  is left
 
             * to keep name of previously used nodes, that still may be used by non-updated extensions.
 
             */
 
            if (isset($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;
 
    }

可以看出,主要工作在getGroupedClassName()中进行,该方法获取类别名catalog/product并通过explode方法去除中间的斜线并创建一个数组。然后该方法加载VarienSimplexml_Element的实例并将数组中的第一个值(group_classname)传入,同时它还是检查此类是否被重写,如果被重写,将会采用相对应的组名。
Magento还使用自定义的uc_words()方法来将首字母大写并还可以转化类别名的分隔符。最终,函数会将真实类名返回给getModelInstance()方法,在这个例子中,返回值为Mage_Catalog_Model_Product。
Magento工厂名及函数

喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址