Magento:在管理订单详情页面添加选项卡

3
我创建了一个自定义的Magento模块,扩展了核心销售订单功能,并添加了一些自定义用户输入。在下单后,我想在管理区域的订单详细页面上显示此数据的自定义标签页。我已成功将新标签显示在选项卡列表中,但是当我单击该选项卡时,会出现404错误。

这是我的代码:

app/code/local/Zac/Attack/etc/config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Zac_Attack>
            <version>0.1.0</version>
        </Zac_Attack>
    </modules>
    <admin>
        <routers>
            <adminhtml>
                <args>
                    <modules>
                        <!-- Override Adminhtml module here. -->
                        <Zac_Attack_Adminhtml before="Mage_Adminhtml">Zac_Attack_Adminhtml</Zac_Attack_Adminhtml>
                    </modules>
                </args>
            </adminhtml>
        </routers>
    </admin>
    <adminhtml>
        <layout>
            <updates>
                <attack>
                    <file>attack.xml</file>
                </attack>
            </updates>
        </layout>
    </adminhtml>
    <global>
        <blocks>
            <attack>
                <class>Zac_Attack_Block</class>
            </attack>
        </blocks>
    <!-- models, resources, etc -->
    </global>
</config>

app/code/local/Zac/Attack/Block/Adminhtml/Sales/Order/View/Tab/Attack.php:

<?php

class Zac_Attack_Block_Adminhtml_Sales_Order_View_Tab_Design extends Mage_Adminhtml_Block_Template
    implements Mage_Adminhtml_Block_Widget_Tab_Interface
{
    protected function _construct()
    {
        parent::_construct();
        $this->setTemplate( 'attack/sales/order/view/tab/attack.phtml' );
    }

    public function getTabLabel()
    {
        return $this->__( 'Attack' );
    }

    public function getTabTitle()
    {
        return $this->__( 'Attack' );
    }

    public function getTabClass()
    {
        return '';
    }

    public function getClass()
    {
        return $this->getTabClass();
    }

    public function getTabUrl()
    {
        // Here the url gets rewritten to my custom name, throws 404 when called...
        // The url takes the form:
        // http://mydomain.com/admin/sales_order/attack/order_id/1/key/65cbb0c2956dd9413570a2ec8761bef5/
        return $this->getUrl('*/*/attack', array('_current' => true));
    }

    public function canShowTab()
    {
        return true;
    }

    public function isHidden()
    {
        return false;
    }

    public function getOrder()
    {
        return Mage::registry( 'current_order' );
    }
}

app/code/local/Zac/Attack/controllers/Adminhtml/Sales/OrderController.php:

<?php

require_once "Mage/Adminhtml/controllers/Sales/OrderController.php";

class Zac_Attack_Adminhtml_Sales_OrderController extends Mage_Adminhtml_Sales_OrderController
{
    public function viewAction()
    {
        // This doesn't get called when viewing the default order detail page.
        // I should see the <h1> output as the only content on the page but I don't.
        die( '<h1>viewAction()</h1>' );
    }

    public function attackAction()
    {
        // This should be called when the url has the pattern '*/*/attack' (as it does
        // when displaying my custom tab) however clicking this tab gives a 404.
        die('<h1>attackAction()</h1>');
    }
}

app/design/adminhtml/default/default/layout/attack.xml

<?xml version="1.0" encoding="UTF-8"?>
<layout>
    <adminhtml_sales_order_view>
        <reference name="sales_order_tabs">
            <action method="addTab">
                <name>order_design_details</name>
                <block>attack/adminhtml_sales_order_view_tab_design</block>
            </action>
        </reference>
    </adminhtml_sales_order_view>
</layout>

似乎出现了控制器覆盖失败的情况。无论是被覆盖的方法"viewAction()"还是自定义操作"attackAction()"都没有被调用。我可以通过打印"Mage::getConfig()->getNode('admin/routers/adminhtml')"来确认配置已经被获取到,因为我能看到如下输出:
Mage_Core_Model_Config_Element Object
(
    [args] => Mage_Core_Model_Config_Element Object
        (
            [module] => Mage_Adminhtml
            [modules] => Mage_Core_Model_Config_Element Object
                (
                    [Mage_Index] => Mage_Index_Adminhtml
                    [Mage_Paygate] => Mage_Paygate_Adminhtml
                    [Mage_Paypal] => Mage_Paypal_Adminhtml
                    [widget] => Mage_Widget_Adminhtml
                    [Mage_GoogleOptimizer] => Mage_GoogleOptimizer_Adminhtml
                    [Mage_GoogleBase] => Mage_GoogleBase_Adminhtml
                    [Mage_Authorizenet] => Mage_Authorizenet_Adminhtml
                    [Mage_Bundle] => Mage_Bundle_Adminhtml
                    [Mage_Centinel] => Mage_Centinel_Adminhtml
                    [Mage_Compiler] => Mage_Compiler_Adminhtml
                    [connect] => Mage_Connect_Adminhtml
                    [Mage_Downloadable] => Mage_Downloadable_Adminhtml
                    [importexport] => Mage_ImportExport_Adminhtml
                    [Mage_PageCache] => Mage_PageCache_Adminhtml
                    [xmlconnect] => Mage_XmlConnect_Adminhtml
                    [EM_DeleteOrder_Adminhtml] => EM_DeleteOrder_Adminhtml
                    [find_feed] => Find_Feed_Adminhtml
                    [moneybookers] => Phoenix_Moneybookers
                    [Zac_Attack_Adminhtml] => Zac_Attack_Adminhtml
                )

            [frontName] => admin
        )

    [use] => admin
)

所以,我的第一个问题是:我添加自定义标签页的方法正确吗?
如果我不是在按照正确的方法进行操作,请告诉我正确的方法或提供一个链接,清晰地概述整个过程(搜索Magento信息时有太多的答案片段,没有足够的完整答案)。
如果我正在按照正确的方法进行操作,为什么我的控制器没有覆盖?
希望我已经提供了足够的细节,使问题变得清晰。如果没有,请随时在评论中发表后续问题,我会很乐意阐述 - 如果我知道如何做到。
提前感谢任何提供的帮助。
谢谢, Zac
附言:我注意到社区部分还有另一个模块覆盖相同的控制器 - 但是该覆盖似乎也没有生效。无论如何,出于调试目的,我已完全删除了第三方模块,以确保没有干扰。

请提供导致404错误的URL地址是什么? - OSdave
我现在无法访问应用程序,但是我能够回忆起它的网址(这可能不完全正确,但是它捕捉了问题):mydomain.com/admin/sales_order/attack/order_id/1/key/[key_value]。内置订单详细信息网址为mydomain.com/admin/sales_order/view/order_id/1/key/[key_value]。请注意,在“/sales_order/”之后的差异。 - Zac Seth
我觉得它看起来还好,不明白为什么会出现404错误。缓存被禁用了吗?如果您愿意,可以将模块上传到某个地方,我会在本地安装中查看。 - OSdave
哇,我终于弄明白问题所在了。原来有另一个模块覆盖了OrderController。如果你看一下配置元素输出,就会看到"EM_DeleteOrder_Adminhtml",这是该项目中的社区模块。现在我必须弄清楚如何正确使用继承树——其他两个模块是否必要以及如何覆盖或排除它们。这对于第三方模块开发者来说肯定很痛苦——两个社区模块覆盖同一个类可能很常见。我想知道是否有好的设计模式可以解决多重继承不足的问题。 - Zac Seth
无论如何,感谢你的时间,戴夫。希望有人能够将我的问题作为应该如何解决的示例(虽然在这个主题上还有其他很好的资源),并意识到我在这里遇到的潜在隐藏问题。 - Zac Seth
显示剩余2条评论
1个回答

1

好吧,这不是我预期的解决方案第一次出现问题。如我在回复OSDave上面的评论中提到的那样,我的模块代码编写得完全正确 - 问题出在另一个模块覆盖了相同的控制器。

供以后参考,如果您认为您已经正确地完成了控制器覆盖(无论是管理还是前端 - 两者应该是相同的),但它没有起作用,我强烈建议使用“Mage :: getConfig() -&gt; getNode('admin / routers / adminhtml')”进行调试。只需确保getNode方法中的XPath适用于您要覆盖的模块,然后查找任何不明显属于Magento的条目。

希望这能节省其他人在这个问题上浪费的时间。

祝好, Zac


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接