我正在使用Magento 1.3(社区版)安装,我正在尝试扩展其中一个核心类的功能.我直接在开发服务器上更改了核心文件,并在那里运行了功能.现在,按照Alan Storm的建议,我将核心文件还原为库存并在/app/code/local树中实现我的更改.我一直在阅读Alan Storm的页面和Josh Pratt的指南,但我无法弄清楚如何将这些例子应用到我的案例中.
问题的核心是 - 为了扩展/猴子修补核心类,我需要实现多少Magento模块的骨架?
基本上我不喜欢这个.
我的场景的细节:我正在尝试改变Magento的产品评论功能.此功能的代码存在于/app/code/core/Mage/Review/.我在提交新评论时向服务器端验证添加了一个额外的步骤(我们的商店存在垃圾邮件问题,因此我添加了一个额外的表单字段,将其隐藏在人类的CSS中,并抛出填写的评论在那个表单字段中;我这样做是因为CAPTCHAs是次优的UI选择).我/app/code/core/Mage/Review/controllers/ProductController.php在Mage_Review_ProductController-> postAction()方法和/app/code/core/Mage/Review/Model/Review.phpMage_Review_Model_Review-> validate()方法中添加了代码.
然后我分离了添加的代码,将其放入/app/code/local/Mage/Review/controllers/ProductController.php并/app/code/local/Mage/Review/Model/Review.php使用了Alan Storm的教程中的"类My_Review_Foo extends Mage_Review_Foo"和"parent :: method"建议.可以预见的是,这打破了产品页面.所以我正在努力/app/code/local/Mage/Review/etc/config.xml想弄清楚如何让Magento使用我的类来扩展核心类.不幸的是,我无法分辨XML的基本逻辑是什么,所以我无法弄清楚如何构建正确的XML来告诉Magento - "无论何时使用核心类,都要使用我的类而不是核心类".
看起来核心类的任何变化几乎都需要Magento插件的完整排序和环境.那是对的吗?我实际上需要做多少来改变我的变化,这样做背后的逻辑是什么?
Magento就是配置.最基本的功能模块除了包含添加或覆盖现有配置XML的配置XML之外什么都不包含.也就是说,大多数开发需求需要实现配置,该配置向系统添加离散的新功能和/或改变现有功能.
有两种方法可以重写块(等同于MVC中的"视图"),帮助程序和模型类,这些方法可以因为包含路径顺序(在Mage集线器类中设置并使用Varien_Autoload),或者 - 更合适 -通过基于配置的重写,在Mage_Core_Model_Config::getGroupedClassName()方法中进行评估.请参阅下面有关基于重写的重写说明Mage_Review_Model_Review.
通过设计(作为安全特征),这些方法都不适用于控制器; 最终保护控制器类定义不被自动加载.接下来是关于如何通过非弃用方法(此时为1.3.0到1.6.1.1)重写动作控制器类的说明.请注意,在Magento CE 1.3.0之前,在动作控制器类中重写功能的方法是通过配置XML.
要重写控制器定义,必须了解如何在Magento中调用控制器类,这通过路由器类进行.Magento核心有四个路由器类.路由器位于FrontController类(Mage_Core_Controller_Front)之间,它们负责匹配请求和更改响应主体.FrontController将循环遍历每个类,并将评估每个类以确定它是否应该处理当前请求.通常这是配置+文件路径约定的问题.实质上,Magento将前缀与初始目录匹配,然后将请求的其余部分与该目录下的路径和文件进行匹配.例如,应用程序中产品页面的文字路径可能是http://demo.magentocommerce.com/review/product/list/id/51/.在此URL结构中,review是frontName(来自配置的节点),并且映射到app/code/core/Mage/Review/controllers/.从那里,产品映射到该目录下的路径和文件名,即ProductController.php,从那里检查已解析的类的列表Action方法.看到?review + product + list是frontName,控制器类路径和方法"resolution params".之后的任何内容都作为请求参数传递(例如id = 51).
从CE 1.3.0开始,可以简单地将一个操作控制器类添加到路由器将检查可解析路径的目录列表中(Mage_Core_Controller_Varien_Router_Standard::collectRoutes()有关详细信息,请参阅参考资料).这是如何工作的典型Magento:通过配置XML!顺便提一下,这种技术既可用于添加新的控制器类路径,也可用于控制器重写.
控制器重写模块至少需要三个文件:
.xml的app/etc/modules/文件)config.xml在模块的etc目录中ProductController.php并位于正在添加的控制器目录的顶部,否则它将与类解析参数不匹配.此外,由于同样的原因,被重写的动作也必须与原始动作相匹配.声明文件将包含以下内容:
<?xml version="1.0" ?>
<config>
<modules>
<Example_Extension>
<active>true</true>
<codePool>local</codePool> <!-- or community -->
</Example_Extension>
</modules>
</config>
Run Code Online (Sandbox Code Playgroud)
基于以上<Example_Extension>和<codePool>节点,应用程序将尝试加载app/code/local/Example/Extension/etc/config.xml.在此文件中,如果有人试图重写Review模块的ProductController类,则需要以下内容:
<?xml version="1.0" ?>
<config>
<frontend>
<routers>
<review>
<args>
<modules>
<some_unique_node before="Mage_Review">Example_Extension</some_unique_node>
<!--
This will map to the controllers directory under the
app/code/local/Example/Extension/ directory. Had this
value been "Example_Extension_Rewrites", the mapping
would be to the
app/code/local/Example/Extension/controllers/Rewrites/
directory. That is just how controller class paths are
evaluated: with a "controllers" directory after two levels
of folders.
-->
</modules>
</args>
</review>
</routers>
</frontend>
</config>
Run Code Online (Sandbox Code Playgroud)
由于该before="Mage_Review"属性,Example_Extension模块的controllers目录将添加到核心Review模块控制器目录之前.因此,如果控制器和动作解析参数在Example_Extension模块中匹配,则将使用其类.如果没有,默认情况将会播出.
最后,要制作的剩余文件是动作控制器类本身.如果目的是继承核心功能,那么从核心类扩展是有意义的.但是,为了让PHP加载核心类的定义,必须直接引用核心类,因为PHP无法通过自动加载器找到定义,如上所述.这意味着require_once在重写的类定义之前添加a .
<?php
require_once 'Mage'.DS.'Review'.DS.'controllers'.DS.'ProductController.php';
class Example_Extension_ProductController extends Mage_Review_ProductController
{
//rewritten and/or new method(s)
}
Run Code Online (Sandbox Code Playgroud)
与Magento中的块,帮助程序和模型类一样,应用程序期望类具有与其在文件系统中的位置相关的特定名称.
关于模型(和块和帮助器)类重写:只需要添加必要的配置XML和类定义.给出这里的示例,重写Mage_Review_Model_Review将需要添加Example_Extension的config.xml:
<config>
<!-- ... -->
<global>
<models>
<review>
<rewrite>
<review>Example_Extension_Model_Review</review>
</rewrite>
</review>
</models>
</global>
</config>
Run Code Online (Sandbox Code Playgroud)
基于此,Mage::getModel('review/review')(或Mage::getSingleton('review/review'))将在内部映射到<rewrite>节点中给出的类名,并将返回重写的类实例.由于如何自动装卸工作(见Varien_Autoload的lib/Varien/Autoload.php),该类定义将需要位于Example/Extension/Model/Review.php并且应该在Example_Extension的声明文件中指定的codePool下.
希望这可以帮助.欲了解更多信息,请随时查看SO以及Magento U的其他帖子.