Übergeben Sie Daten an getChildHtml () oder rufen Sie die Methode für den untergeordneten Block auf

12

Ich möchte Daten an den Aufruf getChildHtml () übergeben können. Der Grund dafür ist, dass die Ausgabe des Blocks von einem Produkttyp abhängt. Also möchte ich das Produkt an getChildHtml übergeben, damit es über die Ausgabe entscheiden kann.

Ich mache das drinnen template/checkout/cart/item/default.phtml.

Im Idealfall würde der Aufruf folgendermaßen aussehen:

echo $this->getChildHtml('child_block_name', $_item);

Dann kann mein Block den Produkttyp aus dem Artikel abrufen und die richtige Ausgabe anzeigen.

Da es definitiv nicht möglich ist, diese Daten weiterzugeben getChildHtml- wie sonst kann diese Art von Verhalten erreicht werden, ohne dass der Kernblock neu geschrieben werden muss

Die beiden Lösungen, die ich derzeit habe, sind wie folgt (beide nicht sehr attraktiv):

1 - Erstellen Sie einen Helfer und greifen Sie über den Helfer auf die HTML-Ausgabe zu, anstatt einen Block und eine Vorlage als Ganzes rendern zu lassen $this->helper('my_module')->getItemHtml($_item);

2 - Greifen Sie auf den untergeordneten Block zu und setzen Sie die Daten in der Vorlage:

 $this->getChild('child_name')->setData('item', $_item);
 echo $this->getChildHtml('child_name')

Ich denke, in Bezug auf die Magento-Architektur ist Nummer 2 das kleinere von zwei Übeln, aber es ist verdammt hässlich, wenn man in eine Vorlage schaut.

Marty Wallace
quelle
Können Sie stattdessen die 'Daten' in der Registrierung oder Sitzung angeben, die der untergeordnete Block verwendet? Verwenden Sie dies in einem Iterator? Was ist der Anwendungsfall?
Philwinkle
Ich glaube nicht, dass die Registrierung hier helfen würde, da die gewünschte Ausgabe von einem Warenkörpertyp abhängt. Dies muss also auf irgendeine Weise an den Block übergeben werden, damit die richtigen Daten ausgegeben werden können. Im Anwendungsfall werden einige zusätzliche Informationen zum Artikel im Warenkorb angezeigt, diese hängen jedoch vom Produkttyp ab
Marty Wallace,
Sie können Produkttypattribute erstellen - möglicherweise erstellen Sie unterschiedliche Attribute basierend auf den Produkttypen? Wenn Sie lieber Ihren eigenen Block erstellen möchten, können wir Ihnen diesbezüglich sicherlich raten, aber es könnte auch einen anderen integrierten Gewinn geben, den ich herausfinden
möchte
Nun, es ist ein Attribut auf Produktebene, auf das ich zugreife, aber die Art und Weise, wie es angezeigt wird, hängt vom Produkttyp ab. Ein gruppiertes Produkt gibt das gleiche Attribut etwas anders wieder als ein einfaches Produkt. Ich verwende einen Block und eine Vorlage für jede Ausgabe
Marty Wallace
Ich habe meine Frage mit einigen Ideen aktualisiert, die ich erwäge, aber mit denen ich nicht 100% zufrieden bin
Marty Wallace

Antworten:

3

Sie können dem übergeordneten Block eine Methode hinzufügen , um das untergeordnete Element abhängig vom Produkttyp abzurufen (ich habe diese Art von Logik einige Male im Kern oder in ähnlicher Form gesehen):

class ParentBlock 
{
    public function getIntuitiveNameChild($item)
    {
        return $this->getChild("intuitive_child")
                    ->setProductType($item->getProductType()) 
                    // You can also decide the product type in this setter, in the Child block.
                    ->setItem($item);
    }

    public function getIntuitiveNameChildDinamically($item)
    {
        return $this->getChild("intuitive_child_" . $item->getProductType())
                    ->setItem($item); 
    }    
}

// parent tpl
// i suggest you avoid getChildHtml(), unless you're certain that methods won't need to be called from the tpl
echo $this->getIntuitiveNameChild($_item)
          // ->someOtherMethod()
          ->toHtml();

In Anbetracht dessen, wie Sie die Layout-XML ändern, um untergeordnete Blöcke hinzuzufügen, könnte es Sie interessieren, wie Magento je nach Produkttyp in Mage_Sales_Block_Items_Abstract::getItemHtml()und entschieden hat, mit Rendering-Markups zu arbeiten Mage_Checkout_Block_Cart_Abstract::getItemHtml().

vergiss es
quelle
Diese Methode umgeht die Layoutstruktur und erzeugt Blöcke, die eng gekoppelt sind (wie alles in Magento ...)
Victor Schröder
12

Die obige Lösung funktioniert nicht, wenn Sie einen untergeordneten Block in einer foreachSchleife anzeigen .

Dazu müssen Sie folgenden Code verwenden:

<?php
foreach ($blocks as $block) {
    $this->getChild("child.block")->setData("my_data", $any_data);
    echo $this->getChildHtml('child.block', false);
}
?>

In child.block können Sie $this->getMyData()die Daten abrufen . Mit dieser Strategie erhält der untergeordnete Block immer die neuesten Daten vom übergeordneten Block.

Der zweite Parameter von getChildHtml()ist $useCache. Wenn Sie false festlegen, wird verhindert, dass die erste Ausgabe zwischengespeichert wird, und das untergeordnete Element wird erneut gerendert.

Arvind07
quelle
4

Ein Block, der Daten empfangen kann, wird als Widget bezeichnet . Dies kann jedoch über mehrere Blockdefinitionen (basierend auf den Eigenschaften von $_item) erfolgen.

Magento macht im Kern etwas sehr Ähnliches, indem es den Zahlungsmethodenblock basierend auf dem Funktionscode der Methode lädt:

<dd>
    <?php echo $this->getChildHtml('payment.method.'.$_code) ?>
</dd>

Sie könnten dasselbe mit diesem Pseudocode machen:

if($type = $_item->getTypeId()){
    $this->getChildHtml('my.block.' . $type);
}

Alles , was einen anderen Blocktyp für jeden Produkttyp zu haben , wäre erfordern würde - bundle, simple, configurable, virtual, grouped. Gar nicht so schlecht.

Wenn Sie wirklich ein Widget verwenden möchten, hat dies Auswirkungen auf Ihre zweite Idee in der bearbeiteten Frage:

<?php
echo $this->getLayout()->createBlock('yourcompany/widget_class')->setType($_item->getTypeId())->toHtml();

Das Erstellen eines Widgets fällt wahrscheinlich nicht in den Geltungsbereich dieser Antwort - ist jedoch nicht besonders schwierig und hat den Vorteil , dass es für CMS-Blöcke wiederverwendet werden kann, obwohl dies für Ihren Anwendungsfall meiner Meinung nach nicht zutreffend ist.

Weitere Informationen zum Erstellen eines Widgets:

http://www.magentocommerce.com/knowledge-base/entry/tutorial-creating-a-magento-widget-part-1

Philwinkle
quelle
Ich bin nicht zu 100% davon überzeugt, dass dies ein guter Ansatz ist, den ich nicht akzeptiert habe.
Marty Wallace
1
Nur ein Widget-Block kann Daten empfangen? Was meinen Sie? Alle Bausteine ​​können Daten empfangen. Ein Widget ist in Magento etwas anderes.
nevvermind
Ich habe nie gesagt, dass sie es nicht könnten. Ich sage per Definition, ein Widget benötigt Dateneingabe, um etwas bedingt anzuzeigen.
Philwinkle
0

Für Magento 2können Sie verwenden

<?php
foreach ($blocks as $block) {
    $block->getChildBlock("child.block")->setData("my_data", $any_data);
    echo $block->getChildHtml('child.block', false);
}
?>

Um die Daten zu erhalten,

$block->getMyData();

Keyur Shah
quelle