上一节我们学习了Magento的基本结构,这一节让我们来看看模块结构(Modular Architecture)和代码池(Code Pools)的相关知识。
Magento是由一个个小的模块组成,通过这些模块来添加具体的功能。这么做的好处是可以轻松的启用和取消某一个模块,一个新的功能也可以通过添加模块来实现。
Autoloader
Magento是一个由3万左右个文件组成的大框架,在应用程序启动时加载每一个文件会让程序变得笨重而缓慢。基于这一原因,Magento在调用一个工厂方法时利用自动加载类来找到所需使用的文件。那个什么是自动加载(Autoloader)呢?
PHP5内置有一个__autoload()的函数,在实际化一个类时,__autoload函数会自动被调用。在这个函数内定义了一个自定义的逻辑来解析类名和需用到的文件。以下是app/mage.php内的一段Magento引导程序代码:
Mage::register('original_include_path', get_include_path()); if (defined('COMPILER_INCLUDE_PATH')) { $appPath = COMPILER_INCLUDE_PATH; set_include_path($appPath . PS . Mage::registry('original_include_path')); include_once COMPILER_INCLUDE_PATH . DS . "Mage_Core_functions.php"; include_once COMPILER_INCLUDE_PATH . DS . "Varien_Autoload.php"; } else { /** * Set include path */ $paths = array(); $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local'; $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community'; $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core'; $paths[] = BP . DS . 'lib'; $appPath = implode(PS, $paths); set_include_path($appPath . PS . Mage::registry('original_include_path')); include_once "Mage/Core/functions.php"; include_once "Varien/Autoload.php"; } Varien_Autoload::register();
引导文件用于定义include包含路径和初始化Varien自动加载器,进而定义自身的autoload函数来作为默认调用函数。下面我们来看看autoload函数(位于lib\Varien下)究竟是做什么用的:
/** * Load class source code * * @param string $class */ public function autoload($class) { if ($this->_collectClasses) { $this->_arrLoadedClasses[self::$_scope][] = $class; } if ($this->_isIncludePathDefined) { $classFile = COMPILER_INCLUDE_PATH . DIRECTORY_SEPARATOR . $class; } else { $classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class))); } $classFile.= '.php'; //echo $classFile;die(); return include $classFile; }
autoload类中只有一个参数$class,它是一个工厂方法提供的别名,这个别名用于生成被引用的匹配类名。正如前所提到过的,Magento的目录结构相当重要,因为类名是通目录结构来获取的,这也是我们后面会看到工厂方法中的一个核心准则。
代码池(Code Pools)
前面也讲过,在app/code文件夹内我们的应用程序代码被分成了三个被称作代码池的目录中,分别是:
- core: Magento提供基础功能的核心模块就放在该文件夹下,Magento开发者的黄金则是在任何情况下都不要去core代码池下的文件。
- community: 第三方的模块放在这一目录下,这里的文件要么是由第三方提供的,要么是通过Magento Connect安装所获取的。
- local: 所有为某一Magento实例开发的模块或代码都放在这一目录中。
代码池表示模块的来源以及加载的顺序,我们再来看一下Mage.php引导文件中的代码,就可以看到代码池的加载顺序:
$paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local'; $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community'; $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core'; $paths[] = BP . DS . 'lib';
这表示对每一个请求类,Magento会先到local中去查看,然后是community,再然后是core,最后则是lib文件夹。这也就形成了一个有趣的现象 ,那就是通过复制core或community中的目录结构并使用相类名,可以轻易的覆盖掉这两个文件夹中的类。
下一节我们一起来看看Magento代码请求流程