Magento的初始化
Magento 初始化是指一个请求到来时,这些初始化一般收集系统的初始化配置数据,并把其缓存起来, 供后继的请求使用。在分配到前端控制器或者路由控制器之前要做的一些系统初始化工作,同时要初始化一些重要的类,供请求后继使用,这些类一般是单例的(整个请求过程只有一个这样的类),理解好系统初始化,对理解 Magento的XML配置数据和Magneto的架构核心代码有很好的帮助。
下面开始magento的初始化过程分析!
在从hello world,开始Magento学习之旅中, 我们在浏览器中输入了http://magentowater/index.php/hello/index/index,从中可以得知Magento的入口 文件为index.php(所有Magento请求都必须经过此文件)。下面我们就打开index.php,通过跟踪代码,顺藤摸瓜方式进行代码跟踪,进而查看magento'是怎么处理一个请求,以及之后的处理.
在index.php中,只有三行代码要注意:
代码块1:
1. $mageFilename = ‘app/Mage.php’;
2. require_once $mageFilename;
3. Mage::run();
第一、二行代码是引入Mage.php文件。这个文件里面分成两部份,一部份是直接马上要执行的一部份,主要功能是设置php的include path,第二部份是Magento中的一个tool类Mage,这个类中的方法和类变量全部是静态的,而且这个类中的方法使用的频率相当之高,一定要搞 清楚。
第二行代码,是调用Mage中的静态方法run:是magento之后要执行的代码。
以下是run方法中主要需要注意的代码,下面为magneto代码。
代码块2:
1. public static function run($code = ”, $type = ‘store’, $options=array())
2. {
3. self::app($code, $type, $options);
4. self::app()->getFrontController()->dispatch();
5. }
第三行代码实现Magento的初始化功能。
第四行代码为前端控制器的dispatch.
Magento整个请求都是由这两行代码进入的,magento的初始化就是这三行,故分析magento的初始化,就是跟踪这三行代码。
代码块3:
1. public static function app($code = ”, $type = ‘store’, $options=array())
2. {
3. if (null === self::$_app) {
4. self::$_app = new Mage_Core_Model_App();
5. Mage::register(‘config’, new Mage_Core_Model_Config());
6. self::$_app->init($code, $type, $options);
7. self::$_app->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS);
8. }
9. return self::$_app;
10. }
以上3,4,5,6,7行代码是app方法的主要代码行。
第4行代码new一个App对像,在Magento,是通过方法调用的方法实例化对象,而不是通过new方法,因为new关键字不是面向抽像,而是面向具体编程,new 关键字被认为是一种硬编码,如果你认为你写的类永远不会发生变化,你也可以用这种方法进行编码,譬如在第4行中的App类。App在整个Magento的 请求过程中都只有一个,是单例,所以可以使用new这种硬编码方式进行编码,可以参考设计模式在Magento中的应用–单例
Mage_Core_Model_App实例被注册到了Mage类中的静态类成员变量_app中,因为我们可以通过Mage中的静态方法取得此对象实例。但是Mage_Core_Model_App中的构造方法为空。所以代码执行到了第5行.
我们知道Magento中有很多xml配置文件。如:app/etc下的config.xml,local.xml,还有app/etc /modules下的所有xml文件,还有每个模块下etc目录下的config.xml.这些配置文件就是Magento的初始化的主角,这些文件统称 Magento的配置文件,xml文件是一个树型结构,除根节点外,任何节点都有一个父节点和0-n个子节点。
第5行代码中new的Mage_Core_Model_Config位于上图中左边的最底层,执行new操作后会执行Mage_Core_Model_Config构造方法,如下:
代码块4:
1. public function __construct($sourceData=null)
2. {
3. $this->setCacheId(‘config_global’);
4. $this->_options = new Mage_Core_Model_Config_Options();
5. parent::__construct($sourceData);
6. }
第3行代码用于设置cache id,Magento的cache中我们将作为一个专题来share,第4行new了一个Mage_Core_Model_Config_Options 类,此类作用是来获取Magneto的各种目录路经的tool类。如果你想得到某个目录的全路经,就可以想到这个类。第5行代码,调用parent的构造 方法,也就是Mage_Core_Model_Config_Base中如下方法:
代码块5:
1. public function __construct($sourceData=null)
2. {
3. $this->_elementClass = ‘Mage_Core_Model_Config_Element’;
4. parent::__construct($sourceData);
5. }
这里重要的代码是第3行,类Mage_core_Model_Config中的_elementClass变量重设为 Mage_Core_Model_Config_Element,默认为:Varien_Simplexml_Element,这一部份在类图中表现为右 边部份。
代码执行到第4行,将执行Varien_Simplexml_Config中的构造方法,由于sourceData参数为null.所以Varien_Simplexml_Config中的构造方法将不会执行.
代码回到了代码块3中的第6行,将执行:Mage_Core_Model_App中的init方法,我们主要分析如下代码:
代码块6:
1. public function init($code, $type=null, $options=array())
2. {
3. $this->_config = Mage::getConfig();
4. $this->_config->init($options);
5. }
上面代码将执行Mage_Core_Model_Config中的init方法.如下:
代码块7:
1. public function init($options=array())
2. {
3. if (is_array($options)) {
4. $this->getOptions()->addData($options);
5. }
6. $etcDir = $this->getOptions()->getEtcDir();
7. $localConfigLoaded = $this->loadFile($etcDir.DS.’local.xml’);
8. $configFile = $etcDir.DS.’config.xml’;
9. $this->loadFile($configFile);
10. $this->_loadDeclaredModules();
11. $this->loadModulesConfiguration(‘config.xml’, $this);
12. $configFile = $etcDir.DS.’local.xml’;
13. if (is_readable($configFile)) {
14. $mergeConfig->loadFile($configFile);
15. $this->extend($mergeConfig);
16. }
17. if ($localConfigLoaded) {
18. $dbConf = $this->getResourceModel();
19. $dbConf->loadToXml($this);
20. file_put_contents(‘c:/magento.xml’,$this->_xml->asXML());
21. }
22. }
代码块7中3,4,5向Mage_Core_Model_Config_Options类实例中(此类为单例)加入options选项,在 Mage::run方法有三个参数:$code = ”, $type = ‘store’, $options=array(),我们一直使用的是默认值,没有作修改,前两个我们将在后面的website/store/store view中详细介绍如何使用,第三个参数options就是在此处加入到Magento中的核心类中,供后继使用。所以在index.php中我们可以传 入我们定义的一些参数给Magento.
第6行得到app/etc目录,第7行加载app/etc/local.xml文件。此次加载是多余的,在我自己使用的Magento中,行7是删 除了,当然,行17的if也可以被删除,这样可以在每个请求来时少加载解析一个xml文件。在我对magento的优化过程,我就做过一些magento 核心代码级的增删。
第8,9行代码是加载app/etc/config.xml文件。loadFile定义在Varien_Simplexml_Config中,也就是在图一左边类图的顶点。
定义如下:
代码块8:
1. public function loadFile($filePath)
2. {
3. $fileData = file_get_contents($filePath);
4. $fileData = $this->processFileData($fileData);
5. return $this->loadString($fileData, $this->_elementClass);
6. }
第3行利用file_get_contents加载变量$filePath文件(此次为app/etc/config.xml),第4行处理一下文 件数据,其实啥都没有做,呵呵。第5行调用loadString方法。其中第二个数据,是我们在代码块5分析过的 Mage_Core_Model_Config_Element,它是php弟SimpleXMLElement 的子类.loadString主要定义如下:
代码块9:
1. public function loadString($string)
2. {
3. $xml = simplexml_load_string($string, $this->_elementClass);
4. $this->_xml = $xml;
5. }
第3行代码,利用simplexml_load_string解析xml文件里的内容(此次为app/etc/config.xml),此方法请参 考PHP Manual中的解释,在PHP Manual中没有传第二个参数,第二个参数据默认为:SimpleXMLElement,在这里我们用他的子类 Mage_Core_Model_Config_Element代替(根据里氏替换原则,任何父类使用的地方,子类也可以使用)。 simplexml_load_string将返回一个Mage_Core_Model_Config_Element实例,持有xml文件的根节点,根 节点又有子节点,所以在根节点实例中有很多Mage_Core_Model_Config_Element实例表示根下直接子节点,直接子节点又有子节 点…,从而形成一个Mage_Core_Model_Config_Element实例的树型对象模型。此根节点将由 Mage_Core_Model_Config中的内部类变量_xml持有,从图1中我们可以看到。
代码执行将回到代码块7的10行,此时的config实例中的_xml已持有app/ect/config.xml文件的内容了。第10行将解析执 行app/etc/modules/下的所有xml文件,xml解析的顺序是,先是:Mage_All.xml文件,然后是以Mage_开头的文件,然后 才是其它文件,这些xml中文件内容,根节点都为<config>,根节点下的所有节点都会合并到config实例中的_xml中去。合并规 则:相同节点,后面将覆盖前面的,不相同则合并。以下如没有说明,都会按此规则合并.
代码执行到11行,此时的config实例中的_xml已持有app/ect/config.xml文件的内容和app/etc/modules /下的所有xml文件的内容。第11将加载所有模块下的ect目录下的config.xml文件了,加载顺序是先是Mage模块,再是其它模块,模块间如 果有depend,先加载被depend的模块。这些文件都会合并到config实例中的_xml中去
代码12-16行将加载app/etc/local.xml文件,这个文件中有我们数据库参数的配置。这个文件中的内容合并到config实例中的_xml中去。
代码18,19主要是把表core_config_data中的数据合并到_xml中去.表core_config_data字段scope有三个 值:default/websites/stores/.字段scope_id意义由scope值决定,如果为default那个scope_id为 0.websites对应的是网站id,stores对应的是网站视图id.合并的规划是这样的:
1、scope为default的将合并到<config><default>节点之下.
2、默认情况下magento的core_store表中有两条数,说明前台,后台由不同的商店视图构成。但后台admin的id为0.在_xml中存在<config><stores><admin>…,<config><stores><default>…如果我们再新建store view如:code为youthor,那么就会多一个<config><stores><youthor>…首先本store view的website下的所有节点。如<config><websites><base>下节点copy到store view下,如:<config><stores><default>下,注意:这里如果有相同的,将不会覆盖,然后再从表core_config_data属于自己商店视图的配置信息,加入到自己商店视图节点下,如:<config><stores><default>下面.
在Magento后台配置系统参数据中,在下拉框中只能选择默认的(默认设置)/网站级/商店视图级,不能选择商店(组)级.当选择默认的(默认设 置),右边的设置项后面没有checkbox,当选择网站级,右边的设置项后面有checkbox,说明为:使用缺省值,默认是勾选的,如果去掉,修改一 下值再保存,将在core_config_data多一条记录,scope就是websites,scope_id为选择的网站id.当选择商店视图级时 右边的设置项后面有checkbox,说明为:使用网站值,默认是勾选的,如果去掉,修改一下值再保存,将在core_config_data多一条记 录,scope就是stores,scope_id为选择的商店视图id.
第20行,我们将合并的xml输出到c盘下的magento.xml下。
global:定义一些全局使用的配置,如models,blocks,helpers,resources,resource等定义.
default:定义默认的参数配置,如上面分析的core_config_data表
modules:定义模块配置
frontend:定义网站前台的配置
adminhtml/admin定义后台的配置
install:安装时要使用的一些配置
websites:定义网站的配置参数,如上面分析的core_config_data表
stores:定义商店的配置参数,如上面分析的core_config_data表
crontab:为定时调度器,也就是定时触发一些程序的一些配置。
总结:
以上表述了magento的初始化流程,分析Magento初始化的大致流程为解析:app/etc/config.xml文件,app/etc/modules/下的所有xml文件,以及每个模块下的etc/config.xml文件,app/etc/local.xml,然后加载core_config_data表中的配置,在解析完毕之后,这些文件最终会合并并存放到Mage_Core_Model_Config中的_xml中,Mage_Core_Model_Config有很多操作_xml文件的方法,_xml持有的对象是Mage_Core_Model_Config_Element.
OK结束!
magneto的初始化完毕!
转载注明地址:MagentoWater