本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
magento的功能已经很强大,但是不同的客户还是有不同的需要,magento不可能都能满足,要改变magento的某些功能行为方式,就不可避免的要修改magento的一些代码,如果只是直接在magento的代码上修改也就没有什么可以说的,但是这样做不好的理由在于,这样会造成下次版本更新时的不便,而且有可能你一不小心更新了magento版本而直接造成了你的修改的全部丢失。 那么有没有一种更好的方式来处理呢?一方面我们即可以实现修改了magento的代码,一方面又不是直接在它的代码上修改而却又让magento能够使用我们的代码。当然是可以的。magento是在zend php framework上开发的,它承袭了zend的许多特性,采用了MVC的架构,也沿袭了zend的类名和目录嵌套相对应的特点。如: - class Mage_Catalog_Model_Category extends Mage_Catalog_Model_Abstract {
- /** * Category display modes */
- const DM_PRODUCT = 'PRODUCTS';
- const DM_PAGE = 'PAGE';
- const DM_MIXED = 'PRODUCTS_AND_PAGE';
- const TREE_ROOT_ID = 1;
复制代码这个类是保存在app/code/core/Mage/Catalog/Model/Category.php文件中,其中,core是代码池名,magento默认自带了community,core,local三个代码池,其中core中保存了magento自身的几乎所有的核心模块代码,Mage则是名字空间名。 我们将要说明的第一种最简单的改写magento代码的方式便是利用了这种类名和目录相对应的特点,先分析一段magento代码: - define('DS', DIRECTORY_SEPARATOR);
- define('PS', PATH_SEPARATOR);
- define('BP', dirname(dirname(__FILE__)));
- Mage::register('original_include_path', get_include_path());
- if (defined('COMPILER_INCLUDE_PATH')) {
- $app_path = COMPILER_INCLUDE_PATH;
- set_include_path($app_path . PS . Mage::registry('original_include_path'));
- include_once "Mage_Core_functions.php";
- include_once "Varien_Autoload.php";
- } else {
- /**
- * Set include path
- */
- $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';
- $app_path = implode(PS, $paths);
- set_include_path($app_path . PS . Mage::registry('original_include_path'));
复制代码其中,magento在原有的包含路径上重新添加了它自己的几个包含路径(include path),分别是local,community,core代码池目录,然后是varien库目录,这样的顺序确定了PHP查询PHP类的顺序,分别是local,community,core,因为magento并没有显式加载任何的库,而是利用了php的__autoload特性,分析一下下列的代码: - Varien_Autoload::register();
- ...
- ...
- ...
- /**
- * Register SPL autoload function
- */
- static public function register()
- {
- spl_autoload_register(array(self::instance(), 'autoload'));
- }
- ...
- ...
- ...
- /**
- * Load class source code
- *
- * @param string $class
- */
- public function autoload($class)
- {
- if ($this->_collectClasses) {
- $this->_arrLoadedClasses[self::$_scope][] = $class;
- }
- if ($this->_isIncludePathDefined) {
- $classFile = $class;
- } else {
- $classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
- }
- $classFile.= '.php';
- //echo $classFile;die();
- return include $classFile;
复制代码其中,下面的这行代码的作用是将当前所需要的类名转换成对应的文件: 第一个str_replace(‘_’, ‘ ‘, $class);是将类名中的各个下划线替换成空格,并将每个单词第一个字母大写。 第二个str_replace则是将上一次调用返回的字符串中的空格替换成路径分隔符,也就是/,这样就确定了类所对应的文件位置。 - $classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
复制代码我们前面知道了,magento中的所有代码的类名都是以名字空间(namespace)为前缀,沿袭目录结构的嵌套层次。而各个代码池即可以有不一样的名字空间,也可以有不一样的名字空间。那么如果你在local代码池(目录)下面创建一个Mage名字空间(目录),那么你几乎可以重写 magento的任意一个类了。比如,我们要重写Mage_Catalog_Model_Category这个类,那么你可以创建下列的文件目录结构: [BP]app/code/local/Mage/Catalog/Model/Category.php 这样你可以直接将原来的文件复制过来,然后你可以做任意修改了,而不用担心版本更新的问题。 上面的这种方法我已经测对model的重写了。block和controller还末测试,不过controller的加载方式似乎有所不同,有待测试。 这只是偷懒的一种方法,事实上magento推荐的方法是通过新建模块,然后在xml中配置重写相应的model,block,controller来实现的。
|