Отладка макета загрузки XML

36

TL; DR: есть ли способ отладить загрузку макета? Как я полагаю, макет одного модуля конфликтует с другим.

Связанный с предыдущим вопросом, который я задал: Как сделать макет модуля, который будет отображаться на всех темах

Я успешно загрузил свой модуль в моей локальной тестовой среде (он же мой компьютер для разработки), проверил переключение между 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
Лучше всего было бы иметь местный env как можно больше, чем en-Pre-Production
Fra
Это то, что я делаю сейчас, но это не так просто, у нас более 20 сторонних модулей, и даже некоторые из них не работают на подготовительной среде, и их разработчики проверяют код.
Ярослав
4
Мне очень любопытно узнать причины, по которым этот вопрос помечен для закрытия как слишком локализованный. Этот вопрос говорит об общей отладке макета, которая, если вы еще не сделали, является весьма полезной и широко применимой.
отметки
Мне тоже любопытно. Но я думаю, что в результате, после нескольких изменений в других, кажется, что я просто пытаюсь решить свою собственную очень локализованную проблему. Да, действительно, но в то же время я все еще надеюсь, что, отладив процесс создания макета, я смогу найти, где находится моя ошибка. Поэтому решение будет полезно для других.
Ярослав

Ответы:

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>
<!-- ... ->
benmarks
источник
Кажется полезным, попробую завтра в первый час
Ярослав
Ваш ответ был правильным, именно то, что я искал. Созданный журнал выводит все дескрипторы, запросы и т. Д. При загрузке страницы. Я подтвердил, что мой дескриптор правильно загружен в массив основных дескрипторов, но по какой-то причине соответствующий блок не загружается / не отображается.
Ярослав
1
И это должно быть проще для устранения неполадок теперь, когда макет был исключен :-).
отметки
Я предполагаю, что вы помещаете это в файл Action.php? Кроме того, как это называется magento?
Метрополис
«Создайте наблюдателя на controller_action_layout_generate_blocks_before» - это вопрос М1.
отметки
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 Можете ли вы проверить, загружается ли product.phtml при изменении типа блока на core/template? Это просто для устранения ошибок в настройках вашего модуля.
Рик Кейперс
1
@ Ярослав, похоже, проблема слишком распространена и ее трудно отладить здесь на stackexchange. Мне не очень понятно, что может вызвать проблему.
Рик Кейперс
12

Я использую PhpStorm с Magicento, и поэтому я подумал, что смогу приспособить @benmarks отличный ответ для своего использования.

В PhpStorm откройте app/code/core/Mage/Core/Controller/Varien/Action.phpи установите точку останова в методе 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 debugger) вы остановитесь на точке останова и увидите это в журнале:

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 - копия из всплывающего окна Evaluate Expression

Баттл Буткус
источник
5

Мы используем расширение Commerce Bug от Alan Storm и считаем его незаменимым для отладки различных вещей в Magento, включая проблемы с макетом. Для макетов вы можете видеть, какие маркеры макета активны на каждой странице, и какие конфигурации макета XML применяются к странице.

Это не бесплатно, но сэкономит много времени на отладку подобных вещей.

Примечание: я никоим образом не связан с Alan Storm или Commerce Bug, я просто счастливый клиент.

Люк Миллс
источник
9
Я являюсь партнером Alan Storm (в том смысле, что он я) и просто хочу отметить, что Commerce Bug 2 также дает вам возможность создать диаграмму направленного графика ваших макетов. alanstorm.com/find_magento_block_name
Алан Шторм
Мы также являемся счастливыми клиентами коммерческой ошибки Alan Storm. Но в системе, где у меня есть эти проблемы, она не установлена, и у нас недостаточно лицензий для всех тестовых и опытных систем. И, кстати, @AlanStorm, привет, мы можем получить обновление для Commerce Bug 2?
Ярослав
1
@Yaroslav Обратитесь в службу поддержки, и мы поможем вам разобраться с обновлениями и обновлениями pulsestorm.net/contact-us
Alan Storm
3

Спасибо Бен Маркс! Это моя версия регистратора разметки 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());
TheKitMurkit
источник