Передайте данные в getChildHtml() или вызовите метод в дочернем блоке


Я хочу иметь возможность передавать данные в вызов getChildHtml(). Причина в том, что выход блока зависит от типа продукта. Поэтому я хочу передать продукт в getChildHtml, чтобы он мог принять решение о выходе.

Я делаю это внутри template/checkout/cart/item/default.phtml.

В идеале вызов должен выглядеть так:

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

Затем мой блок может получить тип продукта из элемента и отобразить правильный вывод.

Так как пройти определенно невозможно эти данные в getChildHtml - как еще можно добиться такого поведения без необходимости переписывать основной блок

В настоящее время у меня есть два решения (ни одно из них не очень привлекательно):

1 - Создайте помощника и получите доступ к выводу html через помощника вместо того, чтобы позволять блоку и шаблону отображать его ala $this->helper('my_module')->getItemHtml($_item);

2 - Доступ к дочернему блоку и установка данных о нем внутри шаблона:

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

Я думаю, что с точки зрения архитектуры Magento номер 2 является меньшим из два зла, но чертовски некрасиво смотреть внутрь шаблона.

Author: Black, 2013-05-15

4 answers

Вы можете добавить метод в родительский блок для извлечения дочернего элемента в зависимости от типа продукта (я пару раз видел такую логику в core или что-то подобное):

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

Тем не менее, видя, как вы изменяете xml-формат макета для добавления дочерних блоков, вам может быть интересно, как Magento решил работать с разметкой рендеринга в зависимости от типов продуктов в Mage_Sales_Block_Items_Abstract::getItemHtml() и Mage_Checkout_Block_Cart_Abstract::getItemHtml().

 3
Author: nevvermind, 2013-05-16 15:54:42

Приведенное выше решение не будет работать, если вы отображаете дочерний блок в цикле foreach.

Для этого вам нужно использовать следующий код:

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

У ребенка.блок, который вы можете использовать $this->getMyData() для получения данных. Используя эту стратегию, дочерний блок всегда будет получать последние данные от родителя.

Вторым параметром getChildHtml() является $useCache. Установка значения false предотвращает кэширование первого вывода и заставляет повторно отображать дочерний элемент.

 12
Author: Arvind07, 2016-04-12 14:41:22

Блок, который может принимать данные, называется виджетом ; хотя это можно сделать с помощью нескольких определений блоков (на основе свойств $_item).

Magento делает что-то очень похожее в ядре, загружая блок способа оплаты на основе короткого кода метода:

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

Вы могли бы сделать то же самое с этим псевдокодом:

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

Все, что потребуется, - это иметь другой тип блока для каждого типа продукта - bundle, simple, configurable, virtual, grouped. Не так уж и плохо, на самом деле.

Если вы действительно хотите использовать виджет - это будет что-то вроде вашей второй идеи в отредактированном вопросе:

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

Создание виджета , вероятно, выходит за рамки этого ответа, но это не так уж сложно, и имеет преимущество в том, что он может быть перепрофилирован для блоков CMS, хотя для вашего случая использования я не думаю, что это применимо.

Для получения дополнительной информации о создании виджет:

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

 4
Author: philwinkle, 2013-05-15 22:48:57

Для Magento 2 вы можете использовать

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

Чтобы получить данные,

$block->getMyData();

 1
Author: Keyur Shah, 2017-07-19 10:21:24