我正在使用Magento 1.3(社区版)安装,我正在尝试扩展其中一个核心类的功能。我直接在开发服务器上更改了核心文件,并在那里运行了功能。现在,following Alan Storm's advice,我正在将核心文件还原为库存并在/app/code/local
树中实现我的更改。我一直在阅读Alan Storm的页面和a guide from 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.php
的Mage_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插件的完整排序和环境。那是对的吗?我实际上需要做多少来改变我的变化,这样做背后的逻辑是什么?
答案 0 :(得分:6)
Magento就是配置。最基本的功能模块除了包含添加或覆盖现有配置XML的配置XML之外什么都不包含。也就是说,大多数开发需求都需要实现配置,这会为系统添加离散的新功能和/或改变现有功能。
有两种方法可以重写块(等同于"视图"在MVC中),帮助器和模型类,这些方法可以因为包含路径顺序(在{{1}中设置)而工作} hub类,由Mage
)使用,或者 - 更合适 - 通过基于配置的重写,在Varien_Autoload
方法中进行评估。请参阅以下有关重写Mage_Core_Model_Config::getGroupedClassName()
的重写说明。
通过设计(作为安全特征)这些方法都不适用于控制器;最终保护控制器类定义不被自动加载。接下来是关于如何通过非弃用方法(此时为1.3.0到1.6.1.1)重写动作控制器类的说明。 请注意,在Magento CE 1.3.0之前,在动作控制器类中重写功能的方法是通过配置XML。
要重写控制器定义,必须了解如何在Magento中调用控制器类,这通过路由器类进行。 Magento核心有四个路由器类。路由器位于FrontController类(Mage_Review_Model_Review
)之间,它们负责匹配请求和更改响应主体。 FrontController将循环遍历每个类,并将评估每个类以确定它是否应该处理当前请求。通常这是配置+文件路径约定的问题。实质上,Magento将前缀与初始目录匹配,然后将请求的其余部分与该目录下的路径和文件进行匹配。例如,应用程序中的产品页面的文字路径可能是http://demo.magentocommerce.com/review/product/list/id/51/。在此网址结构中,审核是 frontName (配置中的一个节点),并且映射到Mage_Core_Controller_Front
。从那里,产品映射到路径&该目录下的文件名,即app/code/core/Mage/Review/controllers/
,并从那里检查已解析的类的列表 操作方法。看到? review + product + list是frontName,controller类路径和方法" resolution params"。之后的任何内容都作为请求参数传递(例如 id = 51 )。
从CE 1.3.0开始,可以简单地将一个操作控制器类添加到路由器将检查可解析路径的目录列表中(有关详细信息,请参阅ProductController.php
)。这是如何工作的典型Magento:通过配置XML!顺便提一下,这种技术既可用于添加新的控制器类路径,也可用于控制器重写。
控制器重写模块至少需要三个文件:
Mage_Core_Controller_Varien_Router_Standard::collectRoutes()
目录下的.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>
和<Example_Extension>
个节点,应用程序将尝试加载<codePool>
。在此文件中,如果有人试图重写Review模块的ProductController类,则需要以下内容:
app/code/local/Example/Extension/etc/config.xml
由于<?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>
属性,Example_Extension模块的控制器目录将添加到核心Review模块控制器目录之前。因此,如果控制器和动作解析参数在Example_Extension模块中匹配,则将使用其类。如果没有,则默认情况将会播出。
最后,要制作的剩余文件是动作控制器类本身。如果目的是继承核心功能,那么从核心类扩展是有意义的。但是,为了让PHP加载核心类的定义,必须直接引用核心类,因为PHP无法通过自动加载器找到定义,如上所述。这意味着在重写的类定义之前添加before="Mage_Review"
。
require_once
就像Magento中的块,帮助器和模型类一样,应用程序期望类具有与其在文件系统中的位置相关的特定名称。
关于模型(和块和帮助器)类重写:只需要添加必要的配置XML和类定义。根据这里的示例,重写<?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)
}
将需要添加Example_Extension的config.xml:
Mage_Review_Model_Review
基于此,<config>
<!-- ... -->
<global>
<models>
<review>
<rewrite>
<review>Example_Extension_Model_Review</review>
</rewrite>
</review>
</models>
</global>
</config>
(或Mage::getModel('review/review')
)将在内部映射到Mage::getSingleton('review/review')
节点中给出的类名,并将返回重写的类实例。由于自动加载器的工作方式(请参阅<rewrite>
上的Varien_Autoload
),该类定义需要位于lib/Varien/Autoload.php
,并且应位于Example_Extension声明中指定的codePool下文件。
希望这会有所帮助。欲了解更多信息,请随时查看SO以及Magento U的其他帖子。