阅读:3353回复:0
修改magento的代码实现特定的功能
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来实现的。 来源:http://blog.csdn.net/xinhaozheng/article/details/4349184 |
|