2011-1-4-----核心模型---mage_core_model_cache---construct方法--个人分析

来源:互联网 发布:ps机做淘宝主图多 编辑:程序博客网 时间:2024/05/18 03:35

 

//construct.initialize内存实例   base on $options

 /**

     * Class constructor. Initialize cache instance based on options

     *

     * @param array $options

     */

    public function __construct(array $options = array())

    {

        $this->_defaultBackendOptions['cache_dir'] = Mage::getBaseDir('cache');

        /**

         * Initialize id prefix

         */

 

        $this->_idPrefix = isset($options['id_prefix']) ? $options['id_prefix'] : '';

 

 

        if (!$this->_idPrefix && isset($options['prefix'])) {

            $this->_idPrefix = $options['prefix'];

        }

        if (empty($this->_idPrefix)) {

            $this->_idPrefix = substr(md5(Mage::getConfig()->getOptions()->getEtcDir()), 0, 3).'_';

        }

 

        $backend    = $this->_getBackendOptions($options);

        $frontend   = $this->_getFrontendOptions($options);

 

        $this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],

            true, true, true

        );

 

        if (isset($options['request_processors'])) {

            $this->_requestProcessors = $options['request_processors'];

        }

    }

 

 

1

$this->_defaultBackendOptions['cache_dir'] = Mage::getBaseDir('cache');

为cache对象属性:_defaultBackendOptions['cache_dir']赋值为var/cache/.

 

 

 

2

//为$this->idPrefix赋值:

取决于$options里面的变量,如:id_prefix,prefix,顺序为:$options['id_prefix']存在,则$this->idPrefix = $options['id_prefix'].如果$options['prefix']存在,则$this->idPrefix = $options[id_prefix],

如果都不存在,下面有介绍。。。。

 $this->_idPrefix = isset($options['id_prefix']) ? $options['id_prefix'] : '';

 

 

        if (!$this->_idPrefix && isset($options['prefix'])) {

            $this->_idPrefix = $options['prefix'];

        }

        if (empty($this->_idPrefix)) {

            $this->_idPrefix = substr(md5(Mage::getConfig()->getOptions()->getEtcDir()), 0, 3).'_';

        }

 

 

3

 $backend    = $this->_getBackendOptions($options);

 

 

//该函数的参数:$cacheOptions,即为construct中的$options参数。

 protected function _getBackendOptions(array $cacheOptions)

    {

        $enable2levels = false;

//1

        $type   = isset($cacheOptions['backend']) ? $cacheOptions['backend'] : $this->_defaultBackend;

//2

        if (isset($cacheOptions['backend_options']) && is_array($cacheOptions['backend_options'])) {

            $options = $cacheOptions['backend_options'];

        } else {

            $options = array();

        }

//

        $backendType = false;

//3

        switch (strtolower($type)) {

            case 'sqlite':

 

                if (extension_loaded('sqlite') && isset($options['cache_db_complete_path'])) {

                    $backendType = 'Sqlite';

                }

                break;

//4

            case 'memcached':

 

                if (extension_loaded('memcache')) {

                    if (isset($cacheOptions['memcached'])) {

                        $options = $cacheOptions['memcached'];

                    }

                    $enable2levels = true;

                    $backendType = 'Memcached';

                }

                break;

            case 'apc':

//5

                if (extension_loaded('apc') && ini_get('apc.enabled')) {

                    $enable2levels = true;

                    $backendType = 'Apc';

                }

                break;

//6

            case 'xcache':

                if (extension_loaded('xcache')) {

                    $enable2levels = true;

                    $backendType = 'Xcache';

                }

                break;

            case 'eaccelerator':

//7

            case 'varien_cache_backend_eaccelerator':

                if (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) {

                    $enable2levels = true;

                    $backendType = 'Varien_Cache_Backend_Eaccelerator';

                }

                break;

//8

            case 'database':

                $backendType = 'Varien_Cache_Backend_Database';

                $options = $this->getDbAdapterOptions();

                break;

//9

            default:

                if ($type != $this->_defaultBackend) {

                    try {

                        if (class_exists($type, true)) {

                            $implements = class_implements($type, true);

                            if (in_array('Zend_Cache_Backend_Interface', $implements)) {

                                $backendType = $type;

                            }

 

                        }

                    } catch (Exception $e) {

                    }

                }

        }

//10

        if (!$backendType) {

            $backendType = $this->_defaultBackend;

            foreach ($this->_defaultBackendOptions as $option => $value) {

                if (!array_key_exists($option, $options)) {

                    $options[$option] = $value;

                }

            }

        }

//11

        $backendOptions = array('type' => $backendType, 'options' => $options);

        if ($enable2levels) {

            $backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);

        }

        return $backendOptions;

    }

 

3.1

$type   = isset($cacheOptions['backend']) ? $cacheOptions['backend'] : $this->_defaultBackend;

 

如果存在$cacheOptions['backend'],则$type等于$cacheOptions['backend'],如果不存在,则$type等于$this->_defaultBackend;

 

 

3.2

 if (isset($cacheOptions['backend_options']) && is_array($cacheOptions['backend_options'])) {

            $options = $cacheOptions['backend_options'];

        } else {

            $options = array();

        }

如果$cacheOptions['backend_options']存在,而且是数组,则$options等于

$cacheOptions['backend_options']

 

 

3.3

 

        switch (strtolower($type)) {

            case 'sqlite':

 

                if (extension_loaded('sqlite') && isset($options['cache_db_complete_path'])) {

                    $backendType = 'Sqlite';

                }

                break;

由3.1可以得出$type,如果

1>$type='sqlite',(sqlite是嵌入式关系数据库),

2>sqlite的需要加载的库文件已经加载

3>($options可以有3.2得出)$options['cache_db_complete_path']存在,则$backendType='sqlite'

总结:

是通过$type的值,库文件的存在性,$options['cache_db_complete_path']是否存在值,进而决定$backendType的值。

------------------>得出$backendTyoe的值

注:

$options['cache_db_complete_path'] = $cacheOptions['backend_options']['cache_db_complete_path']。

3.4

//4

            case 'memcached':

 

                if (extension_loaded('memcache')) {

                    if (isset($cacheOptions['memcached'])) {

                        $options = $cacheOptions['memcached'];

                    }

                    $enable2levels = true;

                    $backendType = 'Memcached';

                }

                break;

mencache:内存显示情况。

 

如果

存在memcached需要加载的库文件则$enable2levels = true;$backendType ='Memcached';

 

如果

1.存在memcached需要加载的库文件

2.isset($cacheOptions['memcached'])

则$options = $cacheOptions['memcached'].

 

如果条件成立->------------------>得出$enable2levels和$backendType的值,对$options重新赋值

 

3.5

 case 'apc':

                if (extension_loaded('apc') && ini_get('apc.enabled')) {

                    $enable2levels = true;

                    $backendType = 'Apc';

                }

                break;

如果apc的库文件加载,而且int_get('apc.enabled')

则$enable2levels =true, $backendType ='Apc'

 

3.6

  case 'xcache':

                if (extension_loaded('xcache')) {

                    $enable2levels = true;

                    $backendType = 'Xcache';

                }

                break;

如果加载了xcache的扩展库文件,则$enable2levels=true,$backendType='Xcache'.

 

 

 

3.7

 

 case 'varien_cache_backend_eaccelerator':

                if (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) {

                    $enable2levels = true;

                    $backendType = 'Varien_Cache_Backend_Eaccelerator';

                }

                break;

如果eaccelerator的扩展库文件加载,ini_get('eaccelerator.enable')

$enable2levels = true;

$backendType = 'Varien_Cache_Backend_Eaccelerator';

 

3.8

  case 'database':

                $backendType = 'Varien_Cache_Backend_Database';

                $options = $this->getDbAdapterOptions();

                break;

如果为database

$backendType = 'Varien_Cache_Backend_Database';

                $options = $this->getDbAdapterOptions();

3.8.1

 

 /**

     * Get options for database backend type

     *

     * @return array

     */

    protected function getDbAdapterOptions()

    {

        $options['adapter_callback'] = array($this, 'getDbAdapter');

        $options['data_table']  = Mage::getSingleton('core/resource')->getTableName('core/cache');

        $options['tags_table']  = Mage::getSingleton('core/resource')->getTableName('core/cache_tag');

        return $options;

    }

得到$options['adapter_callback'] ,$options['data_table'],$options['tags_table']的值。

 

3.9

  default:

                if ($type != $this->_defaultBackend) {

                    try {

                        if (class_exists($type, true)) {

                            $implements = class_implements($type, true);

                            if (in_array('Zend_Cache_Backend_Interface', $implements)) {

                                $backendType = $type;

                            }

                        }

                    } catch (Exception $e) {

                    }

                }

        }

 

如果type不等于$this->_defaultBackend(此值为'file'),而且存在type这个类,这个类实现了zend_cache_backend_INterface这个接口。

$backendType = $type;

 

 

3.10

 if (!$backendType) {

            $backendType = $this->_defaultBackend;

            foreach ($this->_defaultBackendOptions as $option => $value) {

                if (!array_key_exists($option, $options)) {

                    $options[$option] = $value;

                }

            }

        }

3.10.1

 /**

     * Default iotions for default backend

     *

     * @var array

     */

    protected $_defaultBackendOptions = array(

        'hashed_directory_level'    => 1,

        'hashed_directory_umask'    => 0777,

        'file_name_prefix'          => 'mage',

    );

 

 

 

如果backendType没有值,也就是上面的这些情况下都没有给backendType赋值,则等于默认值file($this->_defaultBackend),如果$this->_defaultBackendOptions的key值不存在于$options中,则将该key-value加入到$options。

 

 

3.11

//11

        $backendOptions = array('type' => $backendType, 'options' => $options);

        if ($enable2levels) {

            $backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);

        }

        return $backendOptions;

    }

 

 

3.11.1

$backendOptions = array('type' => $backendType, 'options' => $options);

return $backendOptions

3.11.2

if ($enable2levels) {

            $backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions);

        }

        return $backendOptions;

3.11.2.1

 

 /**

     * Initialize two levels backend model options

     *

     * @param array $fastOptions fast level backend type and options

     * @param array $cacheOptions all cache options

     * @return array

     */

    protected function _getTwoLevelsBackendOptions($fastOptions, $cacheOptions)

    {

        $options = array();

        $options['fast_backend']                = $fastOptions['type'];

        $options['fast_backend_options']        = $fastOptions['options'];

        $options['fast_backend_custom_naming']  = true;

        $options['fast_backend_autoload']       = true;

        $options['slow_backend_custom_naming']  = true;

        $options['slow_backend_autoload']       = true;

 

        if (isset($cacheOptions['slow_backend'])) {

            $options['slow_backend'] = $cacheOptions['slow_backend'];

        } else {

            $options['slow_backend'] = $this->_defaultBackend;

        }

        if (isset($cacheOptions['slow_backend_options'])) {

            $options['slow_backend_options'] = $cacheOptions['slow_backend_options'];

        } else {

            $options['slow_backend_options'] = $this->_defaultBackendOptions;

        }

        if ($options['slow_backend'] == 'database') {

            $options['slow_backend'] = 'Varien_Cache_Backend_Database';

            $options['slow_backend_options'] = $this->getDbAdapterOptions();

        }

 

        $backend = array(

            'type'      => 'TwoLevels',

            'options'   => $options

        );

        return $backend;

    }

 

//由于不是很懂cache,对于这些复杂的赋值,只知道赋值的结果,而不知道这些赋值有什么作用,现就分析到这里吧。总归

 

 $backendOptions = array('type' => $backendType, 'options' => $options);

 

 return  $backendOptions

返回一个type和options的数组。

type指明类型:  file,database,eaccelerator,xcache,apc,memcached,sqlite等

options指明:   这个type需要用到的一个数值,options是一个数组,包含需要用到的值对。

 

 

 

 

4

$frontend   = $this->_getFrontendOptions($options);

 

 /**

     * Get options of cache frontend (options of Zend_Cache_Core)

     *

     * @param   array $cacheOptions

     * @return  array

     */

    protected function _getFrontendOptions(array $cacheOptions)

    {

        $options = isset($cacheOptions['frontend_options']) ? $cacheOptions['frontend_options'] : array();

        if (!array_key_exists('caching', $options)) {

            $options['caching'] = true;

        }

        if (!array_key_exists('lifetime', $options)) {

            $options['lifetime'] = isset($cacheOptions['lifetime']) ? $cacheOptions['lifetime'] : self::DEFAULT_LIFETIME;

        }

        if (!array_key_exists('automatic_cleaning_factor', $options)) {

            $options['automatic_cleaning_factor'] = 0;

        }

        $options['cache_id_prefix'] = $this->_idPrefix;

        return $options;

    }

 

 

 

 

 

 

 

5

 

 $this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],

            true, true, true

        );

 

 

Mage_Core_Model_Cache->_frontend的赋值:

5.1

 

  /**

     * Factory

     *

     * @param mixed  $frontend        frontend name (string) or Zend_Cache_Frontend_ object

     * @param mixed  $backend         backend name (string) or Zend_Cache_Backend_ object

     * @param array  $frontendOptions associative array of options for the corresponding frontend constructor

     * @param array  $backendOptions  associative array of options for the corresponding backend constructor

     * @param boolean $customFrontendNaming if true, the frontend argument is used as a complete class name ; if false, the frontend argument is used as the end of "Zend_Cache_Frontend_[...]" class name

     * @param boolean $customBackendNaming if true, the backend argument is used as a complete class name ; if false, the backend argument is used as the end of "Zend_Cache_Backend_[...]" class name

     * @param boolean $autoload if true, there will no #require_once for backend and frontend (usefull only for custom backends/frontends)

     * @throws Zend_Cache_Exception

     * @return Zend_Cache_Core|Zend_Cache_Frontend

     */

 

    public static function factory($frontend, $backend, $frontendOptions = array(), $backendOptions = array(), $customFrontendNaming = false, $customBackendNaming = false, $autoload = false)

    {

        if (is_string($backend)) {

//1

            $backendObject = self::_makeBackend($backend, $backendOptions, $customBackendNaming, $autoload);

        } else {

            if ((is_object($backend)) && (in_array('Zend_Cache_Backend_Interface', class_implements($backend)))) {

                $backendObject = $backend;

            } else {

                self::throwException('backend must be a backend name (string) or an object which implements Zend_Cache_Backend_Interface');

            }

        }

        if (is_string($frontend)) {

            $frontendObject = self::_makeFrontend($frontend, $frontendOptions, $customFrontendNaming, $autoload);

        } else {

            if (is_object($frontend)) {

                $frontendObject = $frontend;

            } else {

                self::throwException('frontend must be a frontend name (string) or an object');

            }

        }

        $frontendObject->setBackend($backendObject);

        return $frontendObject;

    }

 

 

 

 

 

5.1.1

 /**

     * Frontend Constructor

     *

     * @param string  $backend

     * @param array   $backendOptions

     * @param boolean $customBackendNaming

     * @param boolean $autoload

     * @return Zend_Cache_Backend

     */

    public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false)

    {

        if (!$customBackendNaming) {

//1

            $backend  = self::_normalizeName($backend);

        }

        if (in_array($backend, Zend_Cache::$standardBackends)) {

            // we use a standard backend

            $backendClass = 'Zend_Cache_Backend_' . $backend;

            // security controls are explicit

            #require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';

        } else {

            // we use a custom backend

            if (!preg_match('~^[/w]+$~D', $backend)) {

                Zend_Cache::throwException("Invalid backend name [$backend]");

            }

            if (!$customBackendNaming) {

                // we use this boolean to avoid an API break

                $backendClass = 'Zend_Cache_Backend_' . $backend;

            } else {

                $backendClass = $backend;

            }

            if (!$autoload) {

                $file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';

                if (!(self::_isReadable($file))) {

                    self::throwException("file $file not found in include_path");

                }

                #require_once $file;

            }

        }

        return new $backendClass($backendOptions);

    }

 

 

 

5.1.1

 /**

     * Normalize frontend and backend names to allow multiple words TitleCased

     *

     * @param  string $name  Name to normalize

     * @return string

     */

    protected static function _normalizeName($name)

    {

        $name = ucfirst(strtolower($name));

        $name = str_replace(array('-', '_', '.'), ' ', $name);

        $name = ucwords($name);

        $name = str_replace(' ', '', $name);

        return $name;

    }

 

标准化这个名字,例如由mage_core_model_config-->mageCoreModelConfig.

 

 

 

总结:

 $this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],

            true, true, true

        );

返回值为

Zend_Cache_Core|Zend_Cache_Frontend,

 

 

 

6

  if (isset($options['request_processors'])) {

            $this->_requestProcessors = $options['request_processors'];

        }

 

总结:

 

根据传入值$options,

得到

1

$this->_defaultBackendOptions['cache_dir'] = Mage::getBaseDir('cache');

2

$this->_idPrefix

3

//backend和$frontend类型为数组。返回一个包含type和options的数组。

$backend    = $this->_getBackendOptions($options);

$frontend   = $this->_getFrontendOptions($options);

 

进而得出

 $this->_frontend = Zend_Cache::factory('Varien_Cache_Core', $backend['type'], $frontend, $backend['options'],

            true, true, true

        );

$this->_frontend 为Zend_Cache_Core|Zend_Cache_Frontend类型

4

$this->_requestProcessors = $options['request_processors'];

 

对cache的机制了解不是很多,还处于模糊阶段,所以对magento的核心cache不能有很好的理解,就先这样吧,知道个大体结构。到此为止。。

 

magento 的cache机制是zendframework框架的,所以,研究这个框架再回来看magento的核心内存机制cache。