Pass data to getChildHtml() or call method on child block
The above solution wont work if you are displaying child block in foreach
loop.
For that you need to use following code:
<?php
foreach ($blocks as $block) {
$this->getChild("child.block")->setData("my_data", $any_data);
echo $this->getChildHtml('child.block', false);
}
?>
In child.block you can use
$this->getMyData()
to get the data.
Using this strategy the child block will always get the latest data from parent.
The second parameter of getChildHtml()
is $useCache
. Setting it to false prevents the first output to be cached and forces rendering the child again.
A block that can receive data is called a widget; though this can be done via multiple block definitions (based on the properties of $_item
).
Magento does something very similar in the core by loading the payment method block based on the method's short code:
<dd>
<?php echo $this->getChildHtml('payment.method.'.$_code) ?>
</dd>
You could do the same with this pseudo-code:
if($type = $_item->getTypeId()){
$this->getChildHtml('my.block.' . $type);
}
All that would require would be to have a different block type for each product type - bundle
, simple
, configurable
, virtual
, grouped
. Not so bad, really.
If you really want to use a widget - it would be something to the effect of your second idea in your edited question:
<?php
echo $this->getLayout()->createBlock('yourcompany/widget_class')->setType($_item->getTypeId())->toHtml();
Creating a widget probably outside of the scope of this answer - but it's not terribly difficult, and has the advantage of being able to be repurposed for CMS blocks, though for your use case I don't think that is applicable.
For more information on creating a widget:
http://www.magentocommerce.com/knowledge-base/entry/tutorial-creating-a-magento-widget-part-1
You can add a method on the parent block to fetch the child depending on the product type (I've seen this kind of logic a couple of times in core or something similar):
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();
Still, seeing how you modify the layout xml to add children blocks, you may be interested in how Magento decided to work with rendering markup depending on product types in Mage_Sales_Block_Items_Abstract::getItemHtml()
and Mage_Checkout_Block_Cart_Abstract::getItemHtml()
.