2011-1-3----mage_core_model_config---------init()方法加载过程---个人分析

来源:互联网 发布:淘宝刷找商家 话术 编辑:程序博客网 时间:2024/04/30 22:36

 

 

****************************************************************************

Mage_core_mode_config

的init过程。

 

 /**

     * Initialization of core configuration

     *

     * @return Mage_Core_Model_Config

     */

    public function init($options=array())

    {

        $this->setCacheChecksum(null);

        $this->_cacheLoadedSections = array();

        $this->setOptions($options);

        $this->loadBase();

 

        $cacheLoad = $this->loadModulesCache();

        if ($cacheLoad) {

            return $this;

        }

        $this->loadModules();

        $this->loadDb();

        $this->saveCache();

        return $this;

    }

 

 

1.

$this->setCacheChecksum(null);

 

 /**

     * Enter description here...

     *

     * @param string $data

     * @return Varien_Simplexml_Config

     */

    public function setCacheChecksum($data)

    {

        if (is_null($data)) {

            $this->_cacheChecksum = null;

        } elseif (false===$data || 0===$data) {

            $this->_cacheChecksum = false;

        } else {

            $this->_cacheChecksum = md5($data);

        }

        return $this;

    }

 

//总结:

对$data用md5加密。然后赋值给$this->_cacheChecksum.

 

 

 

 

 

2

$this->_cacheLoadedSections = array();

 

 

/**

     * Loaded Configuration by cached sections

     *

     * @var array

     */

    protected $_cacheLoadedSections = array();

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3

$this->setOptions($options);

 

如果传入的数据中有$options,则赋值

$this->getOptions()->addData($options);

 

 

4

$this->loadBase();

 

 /**

     * Load base system configuration (config.xml and local.xml files)

     *

     * @return Mage_Core_Model_Config

     */

    public function loadBase()

    {

        $etcDir = $this->getOptions()->getEtcDir();

        $files = glob($etcDir.DS.'*.xml');

        $this->loadFile(current($files));

        while ($file = next($files)) {

            $merge = clone $this->_prototype;

            $merge->loadFile($file);

            $this->extend($merge);

        }

        if (in_array($etcDir.DS.'local.xml', $files)) {

            $this->_isLocalConfigLoaded = true;

        }

        return $this;

    }

 

4.1

 $etcDir = $this->getOptions()->getEtcDir();

 

 

4.1.1

 

//MAGE_CORE_MODEL_CONFIG_OPTIONS

 public function getEtcDir()

    {

        //return $this->getDataSetDefault('etc_dir', $this->getAppDir().DS.'etc');

        return $this->_data['etc_dir'];

    }

 

在 MAGE_CORE_MODEL_CONFIG_OPTIONS 初始化函数里面:

 $this->_data['etc_dir']     = $appRoot.DS.'etc';

//总结

得到的是app/ect

 

 

4.2

//glob()函数的作用是:以数组的形式返回与指定模式相匹配的文件名或目录

$files = glob($etcDir.DS.'*.xml');

//app/etc下面的所有配置文件。

 

 

4.3

 

$this->loadFile(current($files));

 

4.3.1

current (array &$array) 

//return mixed The current function simply returns the

 * value of the array element that's currently being pointed to by the

 * internal pointer. It does not move the pointer in any way. If the

 * internal pointer points beyond the end of the elements list or the array is 

 * empty, current returns false.

 

4.3.2

 /**

     * Imports XML file

     *

     * @param string $filePath

     * @return boolean

     */

    public function loadFile($filePath)

    {

        if (!is_readable($filePath)) {

            //throw new Exception('Can not read xml file '.$filePath);

            return false;

        }

 

        $fileData = file_get_contents($filePath);

        $fileData = $this->processFileData($fileData);

        return $this->loadString($fileData, $this->_elementClass);

    }

4.3.2.1

// Reads entire file into a string

 $fileData = file_get_contents($filePath);

4.3.2.2

// processFileData

    /**

     * Stub method for processing file data right after loading the file text

     *

     * @param string $text

     * @return string

     */

    public function processFileData($text)

    {

        return $text;

    }

 

4.3.2.3

//$this->loadString($fileData, $this->_elementClass);

  /**

     * Imports XML string

     *

     * @param  string $string

     * @return boolean

     */

    public function loadString($string)

    {

        if (is_string($string)) {

            $xml = simplexml_load_string($string, $this->_elementClass);

 

            if ($xml instanceof Varien_Simplexml_Element) {

                $this->_xml = $xml;

                return true;

            }

        } else {

            Mage::logException(new Exception('"$string" parameter for simplexml_load_string is not a string'));

        }

        return false;

    }

4.3.2.3.1

$fileData = file_get_contents($filePath);

 

$this->_elementClass就是在mode/config/base.php初始化的时候,赋值的

$this->_elementClass = 'Mage_Core_Model_Config_Element';

 

4.3.2.3.2

//Interprets a string of XML into an object

//return SimpleXMLElement an object of class SimpleXMLElement with

 * properties containing the data held within the XML document

simplexml_load_string()

通过一个xml文件,返回一个SimpleXMLElement类型的对象。

//

 $xml = simplexml_load_string($string, $this->_elementClass);

从这里看。貌似mage_core_model_config_element是从把string变成xml对象(Varien_Simplexml_Element类型的对象)服务的。

4.3.2.3.3

$xml instanceof Varien_Simplexml_Element

判断$xml是否为Varien_Simplexml_Element()类型的对象。

 

 

 

小结:首先找到配置文件目录,然后通过file_get_contents($filePath),把文件读取到string中,通过$xml = simplexml_load_string($string, $this->_elementClass),

生成Varien_Simplexml_Element()类型的对象。

$this->loadFile(current($files));的作用就是读取xml文件,生成Varien_Simplexml_Element,赋值于$this->_xml.

故mage_core_model_config_element为读取xml生成varien_simplexml_element对象。

 

 

 

4.4

 $merge = clone $this->_prototype;

            $merge->loadFile($file);

            $this->extend($merge);

4.4.1

$merge->loadFile($file);

和4.3---$this->loadFile(),是一样的效果,不过他写入的类是:mage_core_model_config_base 生成的对象$merge的属性--->_xml(varien_simplexml_Element),

4.4.2

 $this->extend($merge);

 /**

     * Enter description here...

     *

     * @param Varien_Simplexml_Config $config

     * @param boolean $overwrite

     * @return Varien_Simplexml_Config

     */

    public function extend(Varien_Simplexml_Config $config, $overwrite=true)

    {

        $this->getNode()->extend($config->getNode(), $overwrite);

        return $this;

    }

 

 

4.4.2.1

 $this->getNode();

 

  /**

     * Returns node found by the $path

     *

     * @see     Varien_Simplexml_Element::descend

     * @param   string $path

     * @return  Varien_Simplexml_Element

     */

    public function getNode($path=null)

    {

        if (!$this->_xml instanceof Varien_Simplexml_Element) {

            return false;

        } elseif ($path === null) {

            return $this->_xml;

        } else {

            return $this->_xml->descend($path);

        }

    }

//

如果$path不是Varien_simplexml_element,则return flase

//

如果$path是null,返回xml,

//

如果不为空,则返回$this->_xml->descend($path);

 

 

 

4.4.2.2

 $this->getNode()->extend($config->getNode(), $overwrite);

 

//$this->getNode()返回的是一个varien_simplexml_element()对象类型。

 /**

     * Extends current node with xml from $source

     *

     * If $overwrite is false will merge only missing nodes

     * Otherwise will overwrite existing nodes

     *

     * @param Varien_Simplexml_Element $source

     * @param boolean $overwrite

     * @return Varien_Simplexml_Element

     */

 

    public function extend($source, $overwrite=false)

    {

        if (!$source instanceof Varien_Simplexml_Element) {

            return $this;

        }

 

        foreach ($source->children() as $child) {

            $this->extendChild($child, $overwrite);

        }

 

        return $this;

    }

 

 

4.4.2.2.1

$source->children()

 

//PHP库函数,Finds children of given node

public function children ($ns = null, $is_prefix = null) {}

 

 

 

4.4.2.2.2

//扩展一个子节点

$this->extendChild($child, $overwrite);

 

 

 /**

     * Extends one node

     *

     * @param Varien_Simplexml_Element $source

     * @param boolean $overwrite

     * @return Varien_Simplexml_Element

     */

    public function extendChild($source, $overwrite=false)

    {

        // this will be our new target node

        $targetChild = null;

 

        // name of the source node

        $sourceName = $source->getName();

 

        // here we have children of our source node

        $sourceChildren = $source->children();

 

        if (!$source->hasChildren()) {

            // handle string node

            if (isset($this->$sourceName)) {

                // if target already has children return without regard

                if ($this->$sourceName->children()) {

                    return $this;

                }

                if ($overwrite) {

                    unset($this->$sourceName);

                } else {

                    return $this;

                }

            }

 

            $targetChild = $this->addChild($sourceName, $source->xmlentities());

            $targetChild->setParent($this);

            foreach ($source->attributes() as $key=>$value) {

                $targetChild->addAttribute($key, $this->xmlentities($value));

            }

            return $this;

        }

 

        if (isset($this->$sourceName)) {

            $targetChild = $this->$sourceName;

        }

 

        if (is_null($targetChild)) {

            // if child target is not found create new and descend

            $targetChild = $this->addChild($sourceName);

            $targetChild->setParent($this);

            foreach ($source->attributes() as $key=>$value) {

                $targetChild->addAttribute($key, $this->xmlentities($value));

            }

        }

 

        // finally add our source node children to resulting new target node

        foreach ($sourceChildren as $childKey=>$childNode) {

            $targetChild->extendChild($childNode, $overwrite);

        }

 

        return $this;

    }

//小结:

将每个xml文件生成的varien_simplexml_element(加载xml),然后通过$this->extend()方法加载原理是:

 while ($file = next($files)) {

            $merge = clone $this->_prototype;

            $merge->loadFile($file);

            $this->extend($merge);

        }

 

//return Varien_Simplexml_Config

$this->extend($merge);

 

//总结:

loadBase函数,读取app/etc/ 下面的所有xml文件,生成varien_simplexml_element对象,赋值于mage_core_model_config 的属性 _xml ,然后mage_core_model_config->loadFole(current($files)),也就是mage_core_model_config读取files数组里面的第一个file,加载,然后通过,This->_prototype(mage_core_model_base),读取next(files),$this->extend((clone $this->_prototype)->loadFile($file));

extend()函数加载子节点

$this为mage_core_model_config;

(clone $this->_prototype)->loadFile($file)为加载xml文件生成varien_simplexml_element对象。

 

while ($file = next($files)) {

            $merge = clone $this->_prototype;

            $merge->loadFile($file);

            $this->extend($merge);

        }

总结:

1.首先mage_core_model_config->loadFile()加载第一个file生成varien_simplexml_element,

2剩下的file,通过mage_core_model_config_base->loadFile($file)加载,

3将mage_core_model_config和mage_core_model_config_base合并

mage_core_model_config->extend(mage_core_model_config_base).

 

//@return Mage_Core_Model_Config

$this->loadBase();

加载app/etc/下面的所有的xml文件,然后赋值于Mage_Core_Model_Config->_xml.

完成对所有xml文件的加载。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4.5

if (in_array($etcDir.DS.'local.xml', $files)) {

            $this->_isLocalConfigLoaded = true;

        }

 

//Checks if a value exists in an array

in_array 

 

 /**

     * Flag which identify what local configuration is loaded

     *

     * @var bool

     */

    protected $_isLocalConfigLoaded = false;

 

 

 

 

5

$cacheLoad = $this->loadModulesCache();

        if ($cacheLoad) {

            return $this;

        }

 

 

 

 

 

5.1

//$this->loadModulesCache();

  /**

     * Load cached modules configuration

     *

     * @return bool

     */

    public function loadModulesCache()

    {

        if (Mage::isInstalled()) {

            if ($this->_canUseCacheForInit()) {

                Varien_Profiler::start('mage::app::init::config::load_cache');

                $loaded = $this->loadCache();

                Varien_Profiler::stop('mage::app::init::config::load_cache');

                if ($loaded) {

                    $this->_useCache = true;

                    return true;

                }

            }

        }

        return false;

    }

 

 

5.1.1

Mage::isInstalled()

 

/**

     * Retrieve application installation flag

     *

     * @param string|array $options

     * @return bool

     */

    public static function isInstalled($options = array())

    {

        if (self::$_isInstalled === null) {

            self::setRoot();

 

            if (is_string($options)) {

                $options = array('etc_dir' => $options);

            }

            $etcDir = 'etc';

            if (!empty($options['etc_dir'])) {

                $etcDir = $options['etc_dir'];

            }

            $localConfigFile = self::getRoot() . DS . $etcDir . DS . 'local.xml';

 

            self::$_isInstalled = false;

 

            if (is_readable($localConfigFile)) {

                $localConfig = simplexml_load_file($localConfigFile);

                date_default_timezone_set('UTC');

                if (($date = $localConfig->global->install->date) && strtotime($date)) {

                    self::$_isInstalled = true;

                }

            }

        }

        return self::$_isInstalled;

    }

 

 

 

5.1.1.1

 

// self::setRoot();

  /**

     * Set application root absolute path

     *

     * @param string $appRoot

     * @throws Mage_Core_Exception

     */

    public static function setRoot($appRoot = '')

    {

        if (self::$_appRoot) {

            return ;

        }

 

        if ('' === $appRoot) {

            // automagically find application root by dirname of Mage.php

            $appRoot = dirname(__FILE__);

        }

 

        $appRoot = realpath($appRoot);

 

        if (is_dir($appRoot) and is_readable($appRoot)) {

            self::$_appRoot = $appRoot;

        } else {

            self::throwException($appRoot . ' is not a directory or not readable by this user');

        }

    }

 

 

 

5.1.2

$this->_canUseCacheForInit()

 

 /**

     * Check if cache can be used for config initialization

     *

     * @return bool

     */

    protected function _canUseCacheForInit()

    {

        return Mage::app()->useCache('config') && $this->_allowCacheForInit

            && !$this->_loadCache($this->_getCacheLockId());

    }

5.1.2.1

Mage::app()->useCache('config')

 

 /**

    * Check whether to use cache for specific component

    *

    * @return boolean

    */

    public function useCache($type=null)

    {

        return $this->_cache->canUse($type);

    }

5.1.2.1.1

 /**

     * Cache object

     *

     * @var Zend_Cache_Core

     */

    protected $_cache;

 

 

 

5.1.2.2

$this->_allowCacheForInit

 

 /**

     * Flach which allow using cache for config initialization

     *

     * @var bool

     */

    protected $_allowCacheForInit = true;

 

 

 

 

5.1.2.3

 

$this->_loadCache($this->_getCacheLockId());

5.1.2.3.1

 /**

     * Get lock flag cache identifier

     *

     * @return string

     */

    protected function _getCacheLockId()

    {

        return $this->getCacheId().'.lock';

    }

5.1.2.3.1.1

 /**

     * Enter description here...

     *

     * @return string

     */

    public function getCacheId()

    {

        return $this->_cacheId;

    }

5.1.2.3.2

$this->_loadCache()

 

 /**

     * Load cached data by identifier

     *

     * @param   string $id

     * @return  string

     */

    protected function _loadCache($id)

    {

        return Mage::app()->loadCache($id);

    }

 

 

5.1.2.3.2.1

  /**

     * Loading cache data

     *

     * @param   string $id

     * @return  mixed

     */

    public function loadCache($id)

    {

        return $this->_cache->load($id);

    }

 

 

 

 

 

 

 

5.1.3

$loaded = $this->loadCache();

 

 /**

     * Enter description here...

     *

     * @return boolean

     */

    public function loadCache()

    {

        if (!$this->validateCacheChecksum()) {

            return false;

        }

 

        $xmlString = $this->_loadCache($this->getCacheId());

        $xml = simplexml_load_string($xmlString, $this->_elementClass);

        if ($xml) {

            $this->_xml = $xml;

            $this->setCacheSaved(true);

            return true;

        }

 

        return false;

    }

 

 

 

 

 

 

6

$this->loadModules();

 

 

 

 

 

 

 

6.1

 /**

     * Load modules configuration

     *

     * @return Mage_Core_Model_Config

     */

    public function loadModules()

    {

        Varien_Profiler::start('config/load-modules');

        $this->_loadDeclaredModules();

        $this->loadModulesConfiguration('config.xml', $this);

 

        /**

         * Prevent local.xml directives overwriting

         */

        $mergeConfig = clone $this->_prototype;

        $this->_isLocalConfigLoaded = $mergeConfig->loadFile($this->getOptions()->getEtcDir().DS.'local.xml');

        if ($this->_isLocalConfigLoaded) {

            $this->extend($mergeConfig);

        }

 

        $this->applyExtends();

        Varien_Profiler::stop('config/load-modules');

        return $this;

    }

6.1.1

 $this->_loadDeclaredModules();

 

 /**

     * Load declared modules configuration

     *

     * @param   null $mergeConfig depricated

     * @return  Mage_Core_Model_Config

     */

    protected function _loadDeclaredModules($mergeConfig = null)

    {

        $moduleFiles = $this->_getDeclaredModuleFiles();

        if (!$moduleFiles) {

            return ;

        }

 

        Varien_Profiler::start('config/load-modules-declaration');

 

        $unsortedConfig = new Mage_Core_Model_Config_Base();

        $unsortedConfig->loadString('<config/>');

        $fileConfig = new Mage_Core_Model_Config_Base();

 

        // load modules declarations

        foreach ($moduleFiles as $file) {

            $fileConfig->loadFile($file);

            $unsortedConfig->extend($fileConfig);

        }

 

        $moduleDepends = array();

        foreach ($unsortedConfig->getNode('modules')->children() as $moduleName => $moduleNode) {

            $depends = array();

            if ($moduleNode->depends) {

                foreach ($moduleNode->depends->children() as $depend) {

                    $depends[$depend->getName()] = true;

                }

            }

            $moduleDepends[$moduleName] = array(

                'module'    => $moduleName,

                'depends'   => $depends,

                'active'    => ('true' === (string)$moduleNode->active ? true : false),

            );

        }

 

        // check and sort module dependens

        $moduleDepends = $this->_sortModuleDepends($moduleDepends);

 

        // create sorted config

        $sortedConfig = new Mage_Core_Model_Config_Base();

        $sortedConfig->loadString('<config><modules/></config>');

 

        foreach ($unsortedConfig->getNode()->children() as $nodeName => $node) {

            if ($nodeName != 'modules') {

                $sortedConfig->getNode()->appendChild($node);

            }

        }

 

        foreach ($moduleDepends as $moduleProp) {

            $node = $unsortedConfig->getNode('modules/'.$moduleProp['module']);

            $sortedConfig->getNode('modules')->appendChild($node);

        }

 

        $this->extend($sortedConfig);

 

        Varien_Profiler::stop('config/load-modules-declaration');

        return $this;

    }

 

 

6.1.1.1

//还不是很明白,应该是得到$string="<config.>"节点下所有数据的配置吧。类型为element。

 /**

     * Imports XML string

     *

     * @param  string $string

     * @return boolean

     */

    public function loadString($string)

    {

        if (is_string($string)) {

            $xml = simplexml_load_string($string, $this->_elementClass);

 

            if ($xml instanceof Varien_Simplexml_Element) {

                $this->_xml = $xml;

                return true;

            }

        } else {

            Mage::logException(new Exception('"$string" parameter for simplexml_load_string is not a string'));

        }

        return false;

    }

 

 

//Interprets a string of XML into an object

//返回类 SimpleXMLElement 的一个对象,该对象的属性包含 XML 文档中的数据

 $xml = simplexml_load_string($string, $this->_elementClass);

 

 

 

 

 

 

6.1.2

 $this->loadModulesConfiguration('config.xml', $this);

//整合所有active的modules,然后把etc里面的内容整合。

//config-》loadString('<config/>');得到只有<config>子节点所在的xml的mage_core_model_config_element类型

  /**

     * Iterate all active modules "etc" folders and combine data from

     * specidied xml file name to one object

     *

     * @param   string $fileName

     * @param   null|Mage_Core_Model_Config_Base $mergeToObject

     * @return  Mage_Core_Model_Config_Base

     */

    public function loadModulesConfiguration($fileName, $mergeToObject = null, $mergeModel=null)

    {

        $disableLocalModules    = !$this->_canUseLocalModules();

 

        if ($mergeToObject === null) {

            $mergeToObject = clone $this->_prototype;

            $mergeToObject->loadString('<config/>');

        }

        if ($mergeModel === null) {

            $mergeModel = clone $this->_prototype;

        }

        $modules = $this->getNode('modules')->children();

        foreach ($modules as $modName=>$module) {

            if ($module->is('active')) {

                if ($disableLocalModules && ('local' === (string)$module->codePool)) {

                    continue;

                }

                $configFile = $this->getModuleDir('etc', $modName).DS.$fileName;

                if ($mergeModel->loadFile($configFile)) {

                    $mergeToObject->extend($mergeModel, true);

                }

            }

        }

        return $mergeToObject;

    }

 

 

 

 

 

6.1.3

  $mergeConfig = clone $this->_prototype;

        $this->_isLocalConfigLoaded = $mergeConfig->loadFile($this->getOptions()->getEtcDir().DS.'local.xml');

6.1.4

$this->extend($mergeConfig);

6.1.5

 

  $this->applyExtends();

 

 

 

7

$this->loadDb();

 

  /**

     * Load config data from DB

     *

     * @return Mage_Core_Model_Config

     */

    public function loadDb()

    {

        if ($this->_isLocalConfigLoaded && Mage::isInstalled()) {

            Varien_Profiler::start('config/load-db');

            $dbConf = $this->getResourceModel();

            $dbConf->loadToXml($this);

            Varien_Profiler::stop('config/load-db');

        }

        return $this;

    }

7.1

 $dbConf = $this->getResourceModel();

 /**

     * Get config resource model

     *

     * @return Mage_Core_Store_Mysql4_Config

     */

    public function getResourceModel()

    {

        if (is_null($this->_resourceModel)) {

            $this->_resourceModel = Mage::getResourceModel('core/config');

        }

        return $this->_resourceModel;

    }

 

 

 

 

 

7.2

  $dbConf->loadToXml($this);

 

 

    /**

     * Load configuration values into xml config object

     *

     * @param Mage_Core_Model_Config $xmlConfig

     * @param string $cond

     * @return Mage_Core_Model_Mysql4_Config_Collection

     */

    public function loadToXml(Mage_Core_Model_Config $xmlConfig, $cond=null)

 

 

8

$this->saveCache();

 

 /**

     * Save configuration cache

     *

     * @param   array $tags cache tags

     * @return  Mage_Core_Model_Config

     */

    public function saveCache($tags=array())

    {

        if (!Mage::app()->useCache('config')) {

            return $this;

        }

        if (!in_array(self::CACHE_TAG, $tags)) {

            $tags[] = self::CACHE_TAG;

        }

        $cacheLockId = $this->_getCacheLockId();

        if ($this->_loadCache($cacheLockId)) {

            return $this;

        }

 

        if (!empty($this->_cacheSections)) {

            $xml = clone $this->_xml;

            foreach ($this->_cacheSections as $sectionName => $level) {

                $this->_saveSectionCache($this->getCacheId(), $sectionName, $xml, $level, $tags);

                unset($xml->$sectionName);

            }

            $this->_cachePartsForSave[$this->getCacheId()] = $xml->asNiceXml('', false);

        } else {

            return parent::saveCache($tags);

        }

 

        $this->_saveCache(time(), $cacheLockId, array(), 60);

        $this->removeCache();

        foreach ($this->_cachePartsForSave as $cacheId => $cacheData) {

            $this->_saveCache($cacheData, $cacheId, $tags, $this->getCacheLifetime());

        }

        unset($this->_cachePartsForSave);

        $this->_removeCache($cacheLockId);

        return $this;

    }

 

 

 

 

8

$this->saveCache();

7.2

 $dbConf->loadToXml($this);

 

5.1.3

$loaded = $this->loadCache();

 

6$this->loadModules();

需要在细致搞搞!!

 

 

 

原创粉丝点击