Débogage du chargement du layout XML

36

TL; DR: existe-t-il un moyen de déboguer le chargement de la mise en page? Comme je crois que la disposition d'un module est en conflit avec un autre.

En rapport avec une question précédente que j'ai faite: Comment faire pour qu'une disposition de module soit montrée sur tous les thèmes

J'ai chargé avec succès mon module sur mon environnement de test local (mon PC de développement), testé la commutation entre 3 thèmes différents et tout va bien. Ensuite, j'ai mis à jour le module sur l'environnement de test ou de "pré-production" que nous avons, où il y a beaucoup de modules différents, certains propriétaires, que nous avons fabriqués. Sur cet environnement, le module ne montre pas ce qui est nécessaire sur la page d'accueil du produit. Après quelques tests, je parviens finalement à la conclusion que le problème devrait être lié au processus de chargement de la mise en page.

Alors, y at-il un moyen de déboguer le chargement de la mise en page, comment différents modules remplacent ou ajoutent leurs propres blocs? Mon point est que je crois qu’au moins un module devrait être en conflit avec le mien. Et comme nous avons tellement de modules, je cherche une approche différente de la désactivation des modules un par un et je vois quelle est la problématique.

Mon fichier config.xml est:

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

Mon fichier d'observateur:

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

Ceci est mon fichier de mise en page:

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

Auparavant eu un légèrement différent où au lieu de <default></default>moi <Product_Campaign_Banner></Product_Campaign_Banner>. Cela a également fonctionné.

Mon fichier product.phtml:

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

Le product.phtmlfichier n'est pas chargé et par conséquent, il showCampaignn'est pas exécuté et il existe tous les fichiers HTML nécessaires.

Yaroslav
la source
2
Le mieux serait d'avoir un env local autant que possible identique à celui de pré-production
Du
C’est ce que je fais en ce moment, mais ce n’est pas facile, nous avons plus de 20 modules tiers et même certains d’entre eux ne fonctionnent pas dans l’environnement de pré-production et leurs développeurs vérifient le code.
Yaroslav
4
Je suis très curieux de savoir pourquoi cette question est considérée comme trop localisée. La question concerne le débogage de la disposition générale, ce qui, si vous ne l’avez pas fait, est très utile et s’applique largement.
Benmarks
Je suis curieux aussi. Mais je pense que cela pourrait avoir pour conséquence qu'après plusieurs modifications apportées à d'autres, j'essaie simplement de résoudre mon propre problème très localisé. Et effectivement, je le suis, mais j’espère en même temps que, en mettant au point le processus de génération de la présentation, je pourrai localiser l’emplacement de mon erreur. Par conséquent, la solution sera utile pour les autres.
Yaroslav

Réponses:

55

Vous pouvez consigner les directives XML de présentation compilées utilisées pour générer des blocs. Créez un observateur sur controller_action_layout_generate_blocks_beforeet, dans la méthode observer, enregistrez le code XML de mise à jour à partir de l'objet de présentation transporté:

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 sortie sera similaire à:

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
la source
Cela semble utile, je l'essayerai demain à la première heure
Yaroslav
Votre réponse était la bonne, exactement ce que je cherchais. Le journal créé génère tous les descripteurs, demandes, etc. au chargement de la page. J'ai confirmé que mon descripteur est correctement chargé dans le tableau de descripteurs principaux, mais pour une raison quelconque, le bloc correspondant n'est pas chargé / affiché.
Yaroslav
1
Et cela devrait être plus facile à résoudre maintenant que la disposition a été exclue :-).
Benmarks
Je suppose que vous mettez cela dans le fichier Action.php? Aussi, comment s'appelle-t-il magento?
Métropole
"Créer un observateur sur controller_action_layout_generate_blocks_before" - Ceci est une question M1.
benmarks
23

Vous pouvez récupérer tous les descripteurs de mise en page de votre contrôleur en procédant comme suit:

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

Ou n'importe où (tant que la mise en page a été initialisée) en utilisant ceci:

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

Cela vous aidera peut-être à déboguer.

MODIFIER

Avez-vous configuré votre fichier config.xml pour spécifier la classe de bloc?

    <blocks>
        <banners>
            <class>My_Banners_Block</class>
        </banners>
    </blocks>
Rick Kuipers
la source
Tous les deux testés, mon descripteur est correctement ajouté à la méthode de l'observateur, mais la présentation n'est pas chargée. Je mettrai à jour ma question avec du code, cela aidera peut-être.
Yaroslav
@Yaroslav a mis à jour ma réponse
Rick Kuipers le
Oui, je l'ai sur la config, mettra à jour ma question.
Yaroslav
@Yaroslav Pouvez-vous vérifier si le fichier product.phtml est chargé lors de la modification du type de bloc en core/template? Ceci est juste pour annuler les erreurs dans les paramètres de votre module.
Rick Kuipers
1
@Yaroslav, il semble que le problème soit un peu trop répandu et difficile à résoudre ici sur stackexchange. Ce qui pourrait causer le problème n’est pas très clair pour moi.
Rick Kuipers
12

J'utilise PhpStorm avec Magicento et j'ai donc pensé adapter la réponse de @benmarks à mon utilisation.

Dans PhpStorm, ouvrez app/code/core/Mage/Core/Controller/Varien/Action.phpet mettez un point de rupture dans la méthode generateLayoutBlocks(). Je pense que le but est de l'insérer n'importe où avant $this->getLayout()->generateBlocks();. Je le mets sur la ligne précédente.

Après avoir inséré le point d'arrêt, indiqué par le point rouge à gauche par le numéro de ligne, vous pouvez cliquer dessus avec le bouton droit de la souris pour personnaliser le comportement. Cliquez sur "Plus" en bas pour ouvrir toutes les options. entrez la description de l'image ici

Une fois que vous l'ouvrez, vous cochez la case "Consigner le message sur la console" (facultatif) et "Consigner l'expression évaluée" (où la magie opère). Copiez ensuite cette adaptation du code de benmark dans la zone de texte. La seule chose que j'ai changée est d'épeler la $requestvariable, comme à Mage::app()->getRequest()chaque fois, et de la changer $oen $this(b / c, nous ne sommes pas dans le contexte de l'observateur ici).

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

Alors maintenant, ça ressemble à ça: L'image montre les paramètres avancés des points d'arrêt

Après avoir exécuté le programme (à l'aide de xdebug ou du débogueur zend), vous vous arrêtez au point d'arrêt et consultez le journal:

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

Il semble y avoir une limite de taille pour les entrées de journal qui pourrait être déterminée par la idea.cycle.buffer.sizepropriété dans le idea.propertiesfichier pour PhpStorm, selon cela . Vous pouvez changer cela ou simplement cliquer avec le bouton droit de la souris sur la fenêtre de code et sélectionner "Evaluer l'expression" dans le menu déroulant, puis copier et coller le code à exécuter, et vous obtiendrez le résultat complet.

Dans la fenêtre contextuelle "Evaluer Expression", vous pouvez cliquer sur le résultat avec le bouton droit de la souris (Windows) et sélectionner "Copier la valeur" pour obtenir l'intégralité de la sortie et la coller ailleurs pour analyse.

PhpStorm - copie de la fenêtre d'évaluation d'évaluation

Buttle Butkus
la source
5

Nous utilisons l' extension Commerce Bug d' Alan Storm et nous la trouvons indispensable pour déboguer une variété d'éléments dans Magento, y compris des problèmes de mise en page. Pour les mises en page, vous pouvez voir quelles poignées de mise en page sont actives sur chaque page et quelles configurations XML de mise en page sont appliquées à la page.

Ce n'est pas gratuit, mais vous gagnerez beaucoup de temps à déboguer ce genre de choses.

Remarque: je ne suis en aucun cas affilié à Alan Storm ou Commerce Bug, mais à un client satisfait.

Luke Mills
la source
9
Je suis affilié à Alan Storm (en ce sens que je suis lui) et je tenais simplement à souligner que Commerce Bug 2 vous donne également la possibilité de générer un diagramme orienté graphique de vos présentations. alanstorm.com/find_magento_block_name
Alan Storm le
Nous sommes également heureux clients du bogue du commerce Alan Storm. Mais le système sur lequel je rencontre ces problèmes n’est pas installé et nous n’avons pas assez de licences pour tous les systèmes de test et de pré-production. Et au fait, @AlanStorm, comment pouvons-nous obtenir la mise à jour du bogue 2 de Commerce?
Yaroslav
1
@Yaroslav Contactez le support et nous vous tiendrons au courant des
Alan Storm
3

Merci Ben Marks! Ceci est ma version de l'enregistreur de mise en page XML que vous avez décrit.

C'est un très long fichier donc j'en ai fait du XML ... :-) Vous pouvez ouvrir avec un éditeur 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>');
  }
}

Et mon config.xml ressemble à ceci dans le nœud:

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

Maintenant, j'espère que mon designer pourra expliquer tout cela ... \ o /

Roger Keulen
la source
0

Vous pouvez ajouter ceci à votre action de contrôleur. Il montrera les poignées de manière plus soignée que var_dump.

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