jjzjj

php - 扩展Magento的核心类时,我需要更改哪种XML结构才能使更改生效?

coder 2024-07-04 原文

我正在使用一个Magento1.3(社区版)安装,我正在尝试扩展其中一个核心类的功能。我直接在开发服务器上更改了核心文件,并在那里实现了功能。现在,following Alan Storm's advice,我将把核心文件还原到stock,并在/app/code/local树中实现我的更改。我一直在阅读Alan Storm的页面和a guide from Josh Pratt,但我不太明白如何将这些例子应用到我的案例中。
问题的核心是-为了扩展/monkey补丁核心类,我需要实现多少完整的magento模块的框架?
我需要创建自己的命名空间吗?
当我命名类时,我应该期望哪些下划线在语法上有意义?
当我编写XML时,哪些标记对应于类层次结构,哪些不对应?
代码的哪些其他部分需要更改才能利用我的更改(如果有的话)?
基本上我不想搞货运崇拜。
我的场景的细节是:我试图改变magento的产品评论功能。此功能的代码位于/app/code/core/Mage/Review/中。当提交新的评论时,我在服务器端验证中添加了一个额外的步骤(我们的商店有垃圾邮件问题,所以我添加了一个额外的表单字段,用css将其隐藏起来,并抛出填充该表单字段的评论;我这样做是因为captchas是次优的ui选择)。我为/app/code/core/Mage/Review/controllers/ProductController.php的mage\u review\u productcontroller->postation()方法和/app/code/core/Mage/Review/Model/Review.php的mage\u review\u model\u 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中的“view”)有两种方法,helper和model类,它们的工作方式要么是因为include path order(在Magehub类中设置并由Varien_Autoload使用),要么更恰当地说是通过基于配置的重写(在Mage_Core_Model_Config::getGroupedClassName()方法中计算)。有关基于重写的重写指令,请参见下文。
通过设计(作为一种安全特性),这些方法都不适用于控制器;最终,控制器类定义会受到保护,不会被自动加载。接下来是关于如何使用非弃用方法重写操作控制器类的说明(此时为1.3.0到1.6.1.1)。注意,在magento ce 1.3.0之前,重写动作控制器类中的功能的方法是通过配置xml。
要重写控制器定义,必须了解如何在magento中调用控制器类,这是通过路由器类实现的。Magento Core有四个路由器类。路由器位于frontcontroller类(Mage_Review_Model_Review)之间,它们负责匹配请求和更改响应体。frontcontroller将遍历每个类,并对每个类进行计算,以确定是否应处理当前请求。通常这是一个配置+文件路径约定的问题。实际上,magento将frontname与初始目录匹配,然后将请求的其余部分与该目录下的路径和文件匹配。例如,应用程序中产品页的文字路径可能是http://demo.magentocommerce.com/review/product/list/id/51/。在这个url结构中,review是frontname(配置中的一个节点),它被映射到Mage_Core_Controller_Front。从那里,产品映射到该目录下的路径和文件名,即app/code/core/Mage/Review/controllers/,并从那里检查已解析类的listaction方法。看到了吗?review+product+list是frontname、controller类路径和方法“resolution params”。之后的任何内容都作为请求参数传递(例如id=51)。
由于ce 1.3.0,可以简单地将一个action controller类添加到一个目录列表中,路由器将在其中检查可解析路径(有关更多信息,请参见ProductController.php)。这是典型的magento:通过配置xml!顺便说一下,这种技术既可以用于添加新的控制器类路径,也可以用于控制器重写。
控制器重写模块至少需要三个文件:
模块声明文件(在Mage_Core_Controller_Varien_Router_Standard::collectRoutes()目录下以.xml结尾的文件)
aapp/etc/modules/在模块的config.xml目录中
与被重写的类具有相同路径分辨率的控制器文件。在上述示例中的类路径为“product”的情况下,该文件必须命名为etc并位于要添加的控制器目录的顶部,否则它将与类解析参数不匹配。同样,由于同样的原因,被重写的动作也必须与原始动作匹配。
声明文件将包含以下内容:

<?xml version="1.0" ?>
<config>
    <modules>
        <Example_Extension>
            <active>true</true>
            <codePool>local</codePool> <!-- or community -->
        </Example_Extension>
    </modules>
</config>

基于上述ProductController.php<Example_Extension>节点,应用程序将尝试加载<codePool>。在此文件中,如果要重写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>

由于属性app/code/local/Example/Extension/etc/config.xml,示例扩展模块的controller s目录将添加在core review模块controller目录之前。因此,如果控制器和操作解析参数在示例扩展模块中匹配,则将使用其类。如果没有,默认的场景就会出现。
最后,要生成的剩余文件是操作控制器类本身。如果目的是从核心功能继承,那么从核心类扩展是有意义的。但是,为了让php加载核心类的定义,必须直接引用核心类,因为php无法通过前面提到的autoloader找到定义。这意味着在重写的类定义之前添加一个before="Mage_Review"
<?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)
}

正如magento中block、helper和model类的情况一样,应用程序希望类具有与它们在文件系统中的位置相关的特定名称。
关于模型(以及块和助手)类重写:只需要添加必要的配置xml和类定义。根据这里的示例,重写require_once需要添加到示例扩展的config.xml中:
<config>
    <!-- ... -->
    <global>
        <models>
            <review>
                <rewrite>
                    <review>Example_Extension_Model_Review</review>
                </rewrite>
            </review>
        </models>
    </global>
</config>

基于此,Mage_Review_Model_Review(或Mage::getModel('review/review'))将在内部映射到Mage::getSingleton('review/review')节点中给定的类名,并返回重写的类实例。由于autoloader是如何工作的(请参见<rewrite>atVarien_Autoload),该类定义将需要位于lib/Varien/Autoload.php处,并且应该位于示例扩展的声明文件中指定的代码池下。
希望这有帮助。欲了解更多信息,请随时查阅其他的职位,以及马金托U。

关于php - 扩展Magento的核心类时,我需要更改哪种XML结构才能使更改生效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8405735/

有关php - 扩展Magento的核心类时,我需要更改哪种XML结构才能使更改生效?的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  4. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  5. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  6. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  7. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  8. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

  9. c - mkmf 在编译 C 扩展时忽略子文件夹中的文件 - 2

    我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。

  10. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

随机推荐