Передайте данные в 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 является меньшим из два зла, но чертовски некрасиво смотреть внутрь шаблона.
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()
.
Приведенное выше решение не будет работать, если вы отображаете дочерний блок в цикле 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 предотвращает кэширование первого вывода и заставляет повторно отображать дочерний элемент.
Блок, который может принимать данные, называется виджетом ; хотя это можно сделать с помощью нескольких определений блоков (на основе свойств $_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
Для Magento 2
вы можете использовать
<?php
foreach ($blocks as $block) {
$block->getChildBlock("child.block")->setData("my_data", $any_data);
echo $block->getChildHtml('child.block', false);
}
?>
Чтобы получить данные,
$block->getMyData();