调试布局XML加载


36

TL; DR:有什么方法可以调试布局的加载?我相信一个模块的布局会与另一个模块冲突。

与我之前提出的问题有关:如何使模块布局显示在所有主题上

我已经成功地将模块加载到了本地测试环境(也就是我的开发PC)上,测试了在3个不同主题之间的切换,这是可以的。然后,我在测试或“生产前”环境中更新了模块,那里有许多不同的模块,有些是我们自己制作的。在这种环境下,该模块不会在产品首页上显示所需的内容。经过一些测试,我最终得出结论,问题应该出在布局加载过程上。

那么,有什么方法可以调试布局的加载,不同的模块如何替换或添加自己的块?我的观点是,我相信至少有一个模块应该与我的模块冲突。而且由于模块太多,我正在寻找一种与逐个禁用模块不同的方法,看看哪一种是有问题的。

我的config.xml文件是:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <Dts_Banners>
            <version>0.1.0</version>
        </Dts_Banners>
    </modules>
    <global>
        <blocks>
            <banners>
                <class>Dts_Banners_Block</class>
            </banners>
        </blocks>
  ....
        <events>
            <controller_action_layout_load_before>
                <observers>
                    <attributesethandle>
                        <class>Dts_Banners_Model_Observer</class>
                        <method>addAttributeSetHandle</method>
                    </attributesethandle>
                </observers>
            </controller_action_layout_load_before>
        </events>
    </global>    
  ....
</config>

我的观察者文件:

<?php
class Dts_Banners_Model_Observer
{
    /**
     * Checks if the search text on the list of active campaigns (dts_banners_admin table) has some of the comma separated text on the product name
     * If text found, add a layout handle PRODUCT_CAMPAIGN_BANNER after PRODUCT_TYPE_<product_type_id> handle
     * This handle is handled on the banners.xml layout file that triggers the use of the Front.php frontend block
     *
     * Event: controller_action_layout_load_before
     *
     * @param Varien_Event_Observer $observer
     */
    public function addAttributeSetHandle(Varien_Event_Observer $observer) {
        $product = Mage::registry('current_product');
        if (!($product instanceof Mage_Catalog_Model_Product)) return;
      ....
      ....
}

这是我的布局文件:

<?xml version="1.0" encoding="UTF-8"?>
<layout version="0.1.0">
    <default>
        <reference name="content">
            <block type="banners/front" name="banners.front" as="banners_front" template="banners/product.phtml" before="-"/>
        </reference>
    </default>
</layout>

以前的地方与<default></default>我以前的地方略有不同<Product_Campaign_Banner></Product_Campaign_Banner>。它也起作用。

我的product.phtml文件:

<div class="visual">
    <?php echo $this->showCampaign(); ?>
</div>

product.phtml文件未加载,因此showCampaign不会执行,并且在其中创建了所有需要的HTML。


2
最好的办法是让本地环境与生产前环境尽可能一样
Fra Frath

那就是我现在正在做的事情,但并不容易,我们有20多个第三方模块,甚至其中一些在预生产环境中也不起作用,并且他们的开发人员正在检查代码。
Yaroslav 2013年

4
好奇知道这个问题背后的原因被标记为过于本地化。这个问题涉及到一般的布局调试,如果您还没有完成的话,它会非常有用并且具有广泛的应用价值。
benmarks

我也很好奇 但是我认为,经过几次对他人的修改后,我似乎正在尝试解决自己的本地化问题。的确如此,但同时我仍然希望通过调试布局生成过程,我能够找到错误所在的位置。因此,该解决方案将对其他人有用。
Yaroslav 2013年

Answers:


55

您可以记录用于生成块的已编译布局XML指令。在上创建一个观察器controller_action_layout_generate_blocks_before,并在观察器方法中记录传输的布局对象中的更新XML:

public function logCompiledLayout($o)
{
    $req  = Mage::app()->getRequest();
    $info = sprintf(
        "\nRequest: %s\nFull Action Name: %s_%s_%s\nHandles:\n\t%s\nUpdate XML:\n%s",
        $req->getRouteName(),
        $req->getRequestedRouteName(),      //full action name 1/3
        $req->getRequestedControllerName(), //full action name 2/3
        $req->getRequestedActionName(),     //full action name 3/3
        implode("\n\t",$o->getLayout()->getUpdate()->getHandles()),
        $o->getLayout()->getUpdate()->asString()
    );

    // Force logging to var/log/layout.log
    Mage::log($info, Zend_Log::INFO, 'layout.log', true);
}

输出将类似于:

2013-01-23T16:24:26+00:00 INFO (6): 
Request: cms
Full Action Name: cms_index_index
Handles:
    default
    cms_page
    STORE_default
    THEME_frontend_default_default
    cms_index_index
    page_two_columns_right
    customer_logged_out
Update XML:
<block name="formkey" type="core/template" template="core/formkey.phtml"/>
<label>All Pages</label>
<!-- ... ->

似乎很有帮助,明天将在第一小时进行尝试
Yaroslav 2013年

您的答案是正确的,正是我一直在寻找的答案。创建的日志在页面加载时输出所有句柄,请求等。我已经确认我的句柄已正确加载到主handles数组中,但是由于某种原因未加载/显示相应的块。
Yaroslav

1
应该是现在更容易进行故障排除布局已经排除了:-)。
benmarks

我假设您将其放在Action.php文件中?另外,magento如何称呼它?
Metropolis

“在上创建观察者controller_action_layout_generate_blocks_before -这是M1问题。
Benmarks

23

您可以通过执行以下操作来检索控制器中的所有布局句柄:

var_dump($this->getLayout()->getUpdate()->getHandles());

或在任何地方(只要布局已初始化)使用此命令:

var_dump(Mage::app()->getLayout()->getUpdate()->getHandles());

也许那将帮助您调试。

编辑

您是否已将config.xml设置为指定块类?

    <blocks>
        <banners>
            <class>My_Banners_Block</class>
        </banners>
    </blocks>

都经过测试,我的句柄已正确添加到观察者方法上,但随后未加载布局。我将用一些代码更新我的问题,也许会有所帮助。
Yaroslav 2013年

@Yaroslav更新了我的答案
Rick Kuipers

是的,我在配置文件中有此信息,它将更新我的问题。
Yaroslav 2013年

@Yaroslav将块类型更改为时,是否可以检查product.phtml是否已加载core/template?这只是为了消除模块设置中的错误。
里克·库珀斯

1
@Yaroslav看起来问题似乎过于广泛了,很难在stackexchange上进行调试。我不太清楚是什么原因引起的。
Rick Kuipers 2013年

12

我将PhpStorm与Magicento结合使用,因此我认为我将对@benmarks做出很好的回答以适应我的用法。

在PhpStorm中,打开app/code/core/Mage/Core/Controller/Varien/Action.php并在method中放置一个断点generateLayoutBlocks()。我认为关键是要在任何地方插入它$this->getLayout()->generateBlocks();。我把它放在前一行。

插入断点(由行号左侧的红点表示)后,可以右键单击它以自定义行为。单击底部的“更多”以打开所有选项。 在此处输入图片说明

打开该窗口后,选中“将消息记录到控制台”(可选)和“记录评估表达式”(发生魔术的位置)框。然后将本标记的适应代码复制粘贴到文本框中。我唯一更改的是每次都拼写出$request变量Mage::app()->getRequest(),然后将$o变量更改为$this(b / c,我们不在此处观察者的上下文中)。

sprintf("\nRequest: %s\nFull Action Name: %s_%s_%s\nHandles:\n\t%s\nUpdate XML:\n%s",Mage::app()->getRequest()->getRouteName(),Mage::app()->getRequest()->getRequestedRouteName(),Mage::app()->getRequest()->getRequestedControllerName(),Mage::app()->getRequest()->getRequestedActionName(),implode("\n\t",$this->getLayout()->getUpdate()->getHandles()),$this->getLayout()->getUpdate()->asString())

所以现在看起来像这样: 该图显示了高级断点设置

运行该程序(使用xdebug或zend调试器)后,您将在断点处停止并在日志中看到以下内容:

Update XML:
<block name="formkey" type="core/template" template="core/formkey.phtml"/>
<label>All Pages</label>
<block type="page/html" name="root" output="toHtml" template="page/2columns-left.phtml">
   <block type="page/html_head" name="head" as="head">
      <action method="addJs">
         <script>jquery/jquery-migrate-1.2.1.min.js</script>
      </action>
      <action method="addJs">
         <script>jquery/jquery-ui/jquery-ui.min.js</script>
      </action>
      <action method="addJs">
         <script>prototype/prototype.js</script>
      </action>
      <action method="addJs" ifconfig="dev/js/deprecation">
         <script>prototype/deprecation.js</script>
      </action>
      <action method="addJs">
         <script>lib/ccard.js</scrip

似乎是可能由确定的日志条目大小限制idea.cycle.buffer.size的财产idea.properties为PhpStorm文件,根据。您可以更改它,或仅右键单击代码窗口,然后从下拉菜单中选择“评估表达式”,然后复制并粘贴代码以在其中执行,您将获得完整的输出。

在“评估表达式”弹出窗口中,您可以在结果上单击鼠标右键(Windows),然后选择“复制值”以获取整个输出并将其粘贴到其他位置进行分析。

PhpStorm-从“评估表达式”弹出窗口复制


5

我们使用Alan Storm的Commerce Bug扩展,发现它对于调试Magento中的各种事物(包括布局问题)是必不可少的。对于布局,您可以查看每个页面上哪些布局句柄处于活动状态,以及哪些布局xml配置正在应用于页面。

它不是免费的,但可以节省大量时间调试此类内容。

注意:我与Alan Storm或Commerce Bug无关,只是一个满意的客户。


9
我是Alan Storm的会员(因为我是他),所以我想指出Commerce Bug 2还使您能够生成布局的有向图。alanstorm.com/find_magento_block_name
艾伦·斯托姆

我们也很高兴Alan Storm商业漏洞的客户。但是在遇到这些问题的系统上,尚未安装,并且我们没有足够的许可证来测试所有测试和预生产系统。顺便说一下,@ AlanStorm,您可以获取Commerce Bug 2的更新吗?
Yaroslav

1
@Yaroslav联系支持部门,我们将为您提供更新和升级pulsestorm.net/contact-us
艾伦·斯托姆

3

谢谢Ben Marks!这是您介绍的xml布局记录器的我的版本。

这是一个很长的文件,所以我用它制成了XML ... :-)您可以使用常规编辑器打开...。

    <?php

class Gn_Optimization_Model_Debug_Layout {
  public function logCompiledLayout($o) {
    $req = Mage::app()->getRequest();

    $routeName = $req->getRouteName();
    $fullname = $req->getRequestedRouteName() . '_' . $req->getRequestedControllerName() . '_' . $req->getRequestedActionName();

    $info = sprintf(
      "\nRequest: %s\nFull Action Name: %s\nHandles:\n\t%s\n",
      $routeName, $fullname, implode("\n\t", $o->getLayout()->getUpdate()->getHandles())
    );

    Mage::log($info, Zend_Log::DEBUG, 'debug.'.$routeName.'.layout.log', true);
    file_put_contents(Mage::getBaseDir('log').DS.'debug.'.$routeName.'.layout.xml',
                      '<?xml version="1.0" encoding="utf-8"?>'.PHP_EOL
                      .'<layout>'.PHP_EOL.
                      $o->getLayout()->getUpdate()->asString().
                      '</layout>');
  }
}

我的config.xml在节点中看起来像这样:

<events>
  <controller_action_layout_generate_blocks_before>
    <observers>
      <gn_optimization_controller_action_layout_generate_blocks_before>
        <type>singleton</type>
        <class>gn_optimization/debug_layout</class>
        <method>logCompiledLayout</method>
      </gn_optimization_controller_action_layout_generate_blocks_before>
    </observers>
  </controller_action_layout_generate_blocks_before>
</events>

现在,我希望我的设计师可以解释所有这些... \ o /


0

您可以将其添加到控制器操作中。与var_dump相比,它将以更简洁的方式显示句柄。

Zend_Debug::dump($this->getLayout()->getUpdate()->getHandles());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.