Magento源码分析索引

在index.php文件中,首先运行的是Mage::run()方法。

1
2
3
4
5
6
7
8
9

self::$_app = new Mage_Core_Model_App();
self::$_events = new Varien_Event_Collection();
self::_setConfigModel($options); // self::$_config = new Mage_Core_Model_Config($options);
self::$_app->run(array(
'scope_code' => $code,
'scope_type' => $type,
'options' => $options,
));

主要代码就这些,得到了一个$_app、$_events、$_config,可以看到大量地方出现$options这个变量,默认是空的,它的作用主要是传递一个配置数组,这样可以修改使用默认的对象,比如配置对象,可以通过$options[‘config_model’]传入自定义的配置模型。

接下来就进入了Mage_Core_Model_App类的run方法。但是Mage类还是提供了一系列的有用的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

public static function reset()
{
self::$_registry = array();
self::$_appRoot = null;
self::$_app = null;
self::$_config = null;
self::$_events = null;
self::$_objects = null;
self::$_isDownloader = false;
self::$_isDeveloperMode = false;
self::$_isInstalled = null;
// do not reset $headersSentThrowsException
}

很多方法都是直接或间接围绕这些变量展开的。比如register和unregister方法提供了把变量注册到$_registry或把变量从$_registry中删除,registry通过键获取注册表中值。

以下是两个重要的工厂方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

public static function getModel($modelClass = '', $arguments = array())
{
return self::getConfig()->getModelInstance($modelClass, $arguments);
}

public static function helper($name)
{
$registryKey = '_helper/' . $name;
if (!self::registry($registryKey)) {
$helperClass = self::getConfig()->getHelperClassName($name);
self::register($registryKey, new $helperClass);
}
return self::registry($registryKey);
}

如下的调用应该不陌生:

1
2

$blogpost = Mage::getModel('weblog/blogpost');

它实际调用的是配置对象的getModelInstance方法,它首先在配置对象中寻找weblog节点,找到了对应的class子节点取出值为Vfeelit_Weblog_Model,然后把blogpost附加上去返回Vfeelit_Weblog_Model_Blogpost,然后实例化这个类,类文件怎么加载?把它转换成Vfeelt/Weblog/Model/Blogpost.php文件是也(自动装载)。 helper函数也差不多。(这里通过配置文件获取完整类名,但是令人困惑的是,只要提供完整类名,类完全是可以自动装载的,这里非要绕个弯,而且weblog/blogpost难道比Vfeelit_Weblog_Model_Blogpost更加具有优势?不见得吧,只是短了一点而已,并且需要把对应信息写入XML的配置文件中。 据说Magento 2使用这个做法)

紧接着应用就伴随着Mage_Core_Model_App对象继续深入。同样,看看它的run()方法:

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

public function run($params)
{
$options = isset($params['options']) ? $params['options'] : array();
//基础配置文件加载 仅仅是app/etc下的local.xml和config.xml文件
$this->baseInit($options);
Mage::register('application_params', $params);

if ($this->_cache->processRequest()) {
$this->getResponse()->sendResponse();
} else {
//加载模块配置,app/etc/moules所有文件和每个模块的etc中的config.xml文件,还包括从数据库中加载配置进来
$this->_initModules();
$this->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS);

if ($this->_config->isLocalConfigLoaded()) {
$scopeCode = isset($params['scope_code']) ? $params['scope_code'] : '';
$scopeType = isset($params['scope_type']) ? $params['scope_type'] : 'store';
//当前商店初始化
$this->_initCurrentStore($scopeCode, $scopeType);
//请求初始化
$this->_initRequest();
Mage_Core_Model_Resource_Setup::applyAllDataUpdates();
}
//前端控制器分发,后续进入路由分发
$this->getFrontController()->dispatch();
}
return $this;
}

调用了baseInit()进行一些基本的初始化。接着就是看是否命中缓存,如果命中就直接返回了,否则就开始初始化模块,初始化当前商店,初始化请求,运行模块自动安装更新脚本,然后获取前端控制器后进行分发。

接下来分
1 Magento的配置对象与全局XML配置文件构建
2 Magento如何从数据库加载配置信息合并到全局XML
3 Magento店铺初始化(布局XML文件构建)
4 Magento的请求初始化
5 Magento的路由分发
6 …..

坚持原创技术分享,您的支持将鼓励我继续创作!