Depuración de carga de XML de diseño

36

TL; DR: ¿hay alguna forma de depurar la carga del diseño? Como creo, el diseño de un módulo está en conflicto con otro.

Relacionado con una pregunta anterior que hice: Cómo hacer que un diseño de módulo se muestre en todos los temas

Cargué con éxito mi módulo en mi entorno de prueba local (también conocido como mi PC de desarrollo), probé el cambio entre 3 temas diferentes y está bien. Luego actualicé el módulo en el entorno de prueba o "preproducción" que tenemos, donde hay muchos módulos diferentes, algunos patentados y otros creados por nosotros. En este entorno, el módulo no muestra lo que se necesita en la página principal del producto. Después de algunas pruebas, finalmente llegué a la conclusión de que el problema debería estar en el proceso de carga de diseño.

Entonces, ¿hay alguna manera de depurar la carga del diseño, cómo los diferentes módulos reemplazan o agregan sus propios bloques? Mi punto es que creo que hay al menos un módulo que debería estar en conflicto con el mío. Y como tenemos tantos módulos, estoy buscando un enfoque diferente a deshabilitar los módulos uno por uno y ver cuál es el problemático.

Mi archivo config.xml es:

<?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>

Mi archivo de observador:

<?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;
      ....
      ....
}

Este es mi archivo de diseño:

<?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>

Anteriormente tenía uno ligeramente diferente en lugar de que <default></default>yo tenía <Product_Campaign_Banner></Product_Campaign_Banner>. También funcionó.

Mi archivo product.phtml:

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

El product.phtmlarchivo no se carga y, por lo tanto, showCampaignno se ejecuta y allí es donde se crea todo el HTML necesario.

Yaroslav
fuente
2
Lo mejor sería tener el ambiente local tanto como sea posible igual que el ambiente de preproducción
Fra
Eso es lo que estoy haciendo en este momento, pero no es fácil, tenemos más de 20 módulos de terceros e incluso algunos de ellos no funcionan en el entorno de preproducción y sus desarrolladores están verificando el código.
Yaroslav el
44
Tengo mucha curiosidad por saber que las razones detrás de esta pregunta se marcan para cerrar como demasiado localizadas. La pregunta se refiere a la depuración de diseño general, que si no lo ha hecho, es bastante útil y ampliamente aplicable.
Benmarks
Yo también tengo curiosidad. Pero creo que, como resultado, después de varias ediciones a otros parece que solo estoy tratando de resolver mi propio problema muy localizado. Y de hecho lo estoy, pero al mismo tiempo todavía espero que al depurar el proceso de generación de diseño pueda encontrar dónde se encuentra mi error. Por lo tanto, la solución será útil para otros.
Yaroslav

Respuestas:

55

Puede registrar las directivas XML de diseño compiladas que se utilizan para generar bloques. Cree un observador controller_action_layout_generate_blocks_beforey, en el método de observador, registre el XML de actualización del objeto de diseño transportado:

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);
}

La salida será similar a:

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>
<!-- ... ->
puntos de referencia
fuente
Parece útil, lo probaré mañana a la primera hora
Yaroslav
Su respuesta fue la correcta, justo lo que estaba buscando. El registro creado genera todos los identificadores, solicitudes, etc. en la carga de la página. He confirmado que mi controlador está cargado correctamente en la matriz de controladores principales, pero por alguna razón el bloque correspondiente no se carga / muestra.
Yaroslav
1
Y eso debería ser más fácil de solucionar ahora que se ha descartado el diseño :-).
Benmarks
¿Asumo que está poniendo esto dentro del archivo Action.php? Además, ¿cómo se llama esto por magento?
Metrópolis
"Crear un observador en controller_action_layout_generate_blocks_before" : esta es una pregunta M1.
Benmarks
23

Puede recuperar todos los controladores de diseño en su controlador haciendo esto:

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

O en cualquier lugar (siempre que el diseño se haya inicializado) usando esto:

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

Quizás eso te ayude a depurar.

EDITAR

¿Ha configurado su config.xml para especificar la clase de bloque?

    <blocks>
        <banners>
            <class>My_Banners_Block</class>
        </banners>
    </blocks>
Rick Kuipers
fuente
Ambos probados, mi identificador se agregó correctamente en el método de observación pero luego el diseño no se carga. Actualizaré mi pregunta con algún código, tal vez sea útil.
Yaroslav
@Yaroslav actualizó mi respuesta
Rick Kuipers el
Sí, tengo eso en la configuración, actualizará mi pregunta.
Yaroslav
@Yaroslav ¿Puedes verificar si el product.phtml se carga al cambiar el tipo de bloque a core/template? Esto es solo para cancelar errores en la configuración de su módulo.
Rick Kuipers el
1
@Yaroslav parece que el problema está demasiado extendido y es difícil de depurar aquí en stackexchange. No está muy claro para mí qué podría causar el problema.
Rick Kuipers el
12

Estoy usando PhpStorm con Magicento, así que pensé en adaptar la excelente respuesta de @benmarks a mi uso.

En PhpStorm, abre app/code/core/Mage/Core/Controller/Varien/Action.phpy pon un punto de quiebre en el método generateLayoutBlocks(). Creo que el punto es insertarlo en cualquier lugar antes $this->getLayout()->generateBlocks();. Lo puse en la línea anterior.

Después de insertar el punto de interrupción, indicado por el punto rojo a la izquierda por el número de línea, puede hacer clic con el botón derecho para personalizar el comportamiento. Haga clic en "Más" en la parte inferior para abrir todas las opciones. ingrese la descripción de la imagen aquí

Una vez que lo abra, marque la casilla "Registrar mensaje en la consola" (opcional) y "Registrar expresión evaluada" (donde ocurre la magia). Luego copie y pegue esta adaptación del código de benmark en el cuadro de texto. Lo único que he cambiado es deletrear la $requestvariable como Mage::app()->getRequest()siempre, y cambié la $ovariable a $this(b / c no estamos en el contexto del observador aquí).

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())

Entonces ahora se ve así: La imagen muestra configuraciones avanzadas de punto de interrupción

Después de ejecutar el programa (usando el depurador xdebug o zend), se detendrá en el punto de interrupción y verá esto en el registro:

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

Parece que hay un límite de tamaño para las entradas de registro que puede determinar la idea.cycle.buffer.sizepropiedad en el idea.propertiesarchivo para PhpStorm, de acuerdo con esto . Puede cambiar eso, o simplemente haga clic derecho en la ventana de código y seleccione "Evaluar expresión" en el menú desplegable, y copie y pegue el código para ejecutarlo allí y obtendrá la salida completa.

En la ventana emergente "Evaluar expresión", puede hacer clic con el botón derecho (Windows) en el resultado y seleccionar "Copiar valor" para obtener el resultado completo y pegarlo en otro lugar para su análisis.

PhpStorm: copia de la ventana emergente Evaluar expresión

Buttle Butkus
fuente
5

Usamos la extensión Commerce Bug de Alan Storm , y la encontramos indispensable para depurar una variedad de cosas en Magento, incluidos los problemas de diseño. Para los diseños, puede ver qué controladores de diseño están activos en cada página y qué configuraciones xml de diseño se están aplicando a la página.

No es gratis, pero ahorrará mucho tiempo depurando este tipo de cosas.

Nota: no estoy afiliado a Alan Storm o Commerce Bug de ninguna manera, solo soy un cliente satisfecho.

Luke Mills
fuente
99
Estoy afiliado con Alan Storm (en eso soy él), y solo quería señalar que Commerce Bug 2 también le da la capacidad de producir un diagrama gráfico dirigido de sus diseños. alanstorm.com/find_magento_block_name
Alan Storm
También somos clientes satisfechos del error comercial de Alan Storm. Pero en el sistema donde tengo estos problemas no está instalado y no tenemos suficientes licencias para todos los sistemas de prueba y preproducción. Y, por cierto, @AlanStorm, ¿podemos obtener la actualización para Commerce Bug 2?
Yaroslav
1
@Yaroslav Póngase en contacto con el servicio de asistencia y lo solucionaremos con actualizaciones y mejoras pulsestorm.net/contact-us
Alan Storm
3

Gracias Ben Marks! Esta es mi versión del registrador de diseño xml que describiste.

Es un archivo muy largo, así que hice XML con él ... :-) Puede abrir con un editor normal ...

    <?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>');
  }
}

Y mi aspecto config.xml es así en el nodo:

<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>

Ahora, espero que mi diseñador pueda explicar todo esto ... \ o /

Roger Keulen
fuente
0

Puede agregar esto a la acción de su controlador. Mostrará manejadores de una manera más ordenada que var_dump.

Zend_Debug::dump($this->getLayout()->getUpdate()->getHandles());
TheKitMurkit
fuente